// Finds first TagHelperAttributeDescriptor matching given name. private static BoundAttributeDescriptor FindFirstBoundAttribute( string name, IEnumerable <TagHelperDescriptor> descriptors) { var firstBoundAttribute = descriptors .SelectMany(descriptor => descriptor.BoundAttributes) .FirstOrDefault(attributeDescriptor => TagHelperMatchingConventions.CanSatisfyBoundAttribute(name, attributeDescriptor)); return(firstBoundAttribute); }
public void CanSatisfyBoundAttribute_IndexerAttribute_ReturnsTrueIfMatching() { // Arrange var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test"); var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind); builder.AsDictionary("asp-", typeof(Dictionary <string, string>).FullName); var boundAttribute = builder.Build(); // Act var result = TagHelperMatchingConventions.CanSatisfyBoundAttribute("asp-route-controller", boundAttribute); // Assert Assert.True(result); }
public override IEnumerable <BoundAttributeDescriptor> GetBoundTagHelperAttributes( TagHelperDocumentContext documentContext, string attributeName, TagHelperBinding binding) { if (documentContext == null) { throw new ArgumentNullException(nameof(documentContext)); } if (attributeName == null) { throw new ArgumentNullException(nameof(attributeName)); } if (binding == null) { throw new ArgumentNullException(nameof(binding)); } var matchingBoundAttributes = new List <BoundAttributeDescriptor>(); foreach (var descriptor in binding.Descriptors) { foreach (var boundAttributeDescriptor in descriptor.BoundAttributes) { if (TagHelperMatchingConventions.CanSatisfyBoundAttribute(attributeName, boundAttributeDescriptor)) { matchingBoundAttributes.Add(boundAttributeDescriptor); // Only one bound attribute can match an attribute break; } } } return(matchingBoundAttributes); }
// Internal for testing internal IReadOnlyList <RazorCompletionItem> GetAttributeParameterCompletions( string attributeName, string parameterName, string containingTagName, IEnumerable <string> attributes, TagHelperDocumentContext tagHelperDocumentContext) { var descriptorsForTag = _tagHelperFactsService.GetTagHelpersGivenTag(tagHelperDocumentContext, containingTagName, parentTag: null); if (descriptorsForTag.Count == 0) { // If the current tag has no possible descriptors then we can't have any additional attributes. return(Array.Empty <RazorCompletionItem>()); } // Attribute parameters are case sensitive when matching var attributeCompletions = new Dictionary <string, HashSet <AttributeDescriptionInfo> >(StringComparer.Ordinal); foreach (var descriptor in descriptorsForTag) { for (var i = 0; i < descriptor.BoundAttributes.Count; i++) { var attributeDescriptor = descriptor.BoundAttributes[i]; var boundAttributeParameters = attributeDescriptor.BoundAttributeParameters; if (boundAttributeParameters.Count == 0) { continue; } if (TagHelperMatchingConventions.CanSatisfyBoundAttribute(attributeName, attributeDescriptor)) { for (var j = 0; j < boundAttributeParameters.Count; j++) { var parameterDescriptor = boundAttributeParameters[j]; if (attributes.Any(name => TagHelperMatchingConventions.SatisfiesBoundAttributeWithParameter(name, attributeDescriptor, parameterDescriptor))) { // There's already an existing attribute that satisfies this parameter, don't show it in the completion list. continue; } if (!attributeCompletions.TryGetValue(parameterDescriptor.Name, out var attributeDescriptionInfos)) { attributeDescriptionInfos = new HashSet <AttributeDescriptionInfo>(); attributeCompletions[parameterDescriptor.Name] = attributeDescriptionInfos; } var descriptionInfo = new AttributeDescriptionInfo( parameterDescriptor.TypeName, descriptor.GetTypeName(), parameterDescriptor.GetPropertyName(), parameterDescriptor.Documentation); attributeDescriptionInfos.Add(descriptionInfo); } } } } var completionItems = new List <RazorCompletionItem>(); foreach (var completion in attributeCompletions) { if (string.Equals(completion.Key, parameterName, StringComparison.Ordinal)) { // This completion is identical to the selected parameter, don't provide for completions for what's already // present in the document. continue; } var razorCompletionItem = new RazorCompletionItem( completion.Key, completion.Key, RazorCompletionItemKind.DirectiveAttributeParameter); var completionDescription = new AttributeCompletionDescription(completion.Value.ToArray()); razorCompletionItem.SetAttributeCompletionDescription(completionDescription); completionItems.Add(razorCompletionItem); } return(completionItems); }