private void HandleUnboundAttribute(AddTagHelperHtmlAttribute attribute, int attributeIndex, RenderTagHelper parent) { if (attribute.ValuePieces != null && (attribute.ValuePieces.Count != 1 || !(attribute.ValuePieces.First() is RenderHtml))) { return; } var plainTextValue = (attribute.ValuePieces?.First() as RenderHtml)?.Html; DeclarePreallocatedTagHelperHtmlAttribute declaration = null; for (var i = 0; i < _classDeclaration.Children.Count; i++) { var current = _classDeclaration.Children[i]; if (current is DeclarePreallocatedTagHelperHtmlAttribute) { var existingDeclaration = (DeclarePreallocatedTagHelperHtmlAttribute)current; if (string.Equals(existingDeclaration.Name, attribute.Name, 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 DeclarePreallocatedTagHelperHtmlAttribute { VariableName = preAllocatedAttributeVariableName, Name = attribute.Name, Value = plainTextValue, ValueStyle = attribute.ValueStyle, }; _classDeclaration.Children.Insert(0, declaration); } var addPreAllocatedAttribute = new AddPreallocatedTagHelperHtmlAttribute { AttributeVariableName = declaration.VariableName }; parent.Children[attributeIndex] = addPreAllocatedAttribute; }
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); } } }