diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperMatchingConventions.cs b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperMatchingConventions.cs index 9aa0ef8059..c1e01760ae 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperMatchingConventions.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperMatchingConventions.cs @@ -12,6 +12,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution { public const string ElementCatchAllName = "*"; + public const char ElementOptOutCharacter = '!'; + public static bool SatisfiesRule( string tagNameWithoutPrefix, string parentTagName, @@ -66,6 +68,17 @@ namespace Microsoft.AspNetCore.Razor.Evolution throw new ArgumentNullException(nameof(rule)); } + if (string.IsNullOrEmpty(tagNameWithoutPrefix)) + { + return false; + } + + if (tagNameWithoutPrefix[0] == ElementOptOutCharacter) + { + // TagHelpers can never satisfy tag names that are prefixed with the opt-out character. + return false; + } + if (rule.TagName != ElementCatchAllName && rule.TagName != null && !string.Equals(tagNameWithoutPrefix, rule.TagName, StringComparison.OrdinalIgnoreCase)) diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperFactsService.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperFactsService.cs index 555b46792c..30e2c381af 100644 --- a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperFactsService.cs +++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperFactsService.cs @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy; using System; using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Linq; namespace Microsoft.VisualStudio.LanguageServices.Razor { @@ -48,8 +47,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor } public override IEnumerable GetBoundTagHelperAttributes( - TagHelperDocumentContext documentContext, - string attributeName, + TagHelperDocumentContext documentContext, + string attributeName, TagHelperBinding binding) { if (documentContext == null) diff --git a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DefaultTagHelperFactsServiceTest.cs b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DefaultTagHelperFactsServiceTest.cs index bffe640ab8..90f0df6420 100644 --- a/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DefaultTagHelperFactsServiceTest.cs +++ b/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DefaultTagHelperFactsServiceTest.cs @@ -13,6 +13,26 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor // Purposefully not thoroughly testing DefaultTagHelperFactsService.GetTagHelperBinding because it's a pass through // into TagHelperDescriptorProvider.GetTagHelperBinding. + [Fact] + public void GetTagHelperBinding_DoesNotAllowOptOutCharacterPrefix() + { + // Arrange + var documentDescriptors = new[] + { + ITagHelperDescriptorBuilder.Create("TestType", "TestAssembly") + .TagMatchingRule(rule => rule.RequireTagName("*")) + .Build() + }; + var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors); + var service = new DefaultTagHelperFactsService(); + + // Act + var binding = service.GetTagHelperBinding(documentContext, "!a", Enumerable.Empty>(), parentTag: null); + + // Assert + Assert.Null(binding); + } + [Fact] public void GetTagHelperBinding_WorksAsExpected() { @@ -133,6 +153,26 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor Assert.Equal(expectedAttributeDescriptors, descriptors, BoundAttributeDescriptorComparer.CaseSensitive); } + [Fact] + public void GetTagHelpersGivenTag_DoesNotAllowOptOutCharacterPrefix() + { + // Arrange + var documentDescriptors = new[] + { + ITagHelperDescriptorBuilder.Create("TestType", "TestAssembly") + .TagMatchingRule(rule => rule.RequireTagName("*")) + .Build() + }; + var documentContext = TagHelperDocumentContext.Create(string.Empty, documentDescriptors); + var service = new DefaultTagHelperFactsService(); + + // Act + var descriptors = service.GetTagHelpersGivenTag(documentContext, "!strong", parentTag: null); + + // Assert + Assert.Empty(descriptors); + } + [Fact] public void GetTagHelpersGivenTag_RequiresTagName() {