From 431a8e195a7261bdf49f63c214b05771c4e4b250 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Mon, 19 Mar 2018 15:52:21 -0700 Subject: [PATCH] [Fixes #2144] Incorrect target element of nested tag helper --- .../DefaultTagHelperCompletionService.cs | 7 +- .../DefaultTagHelperCompletionServiceTest.cs | 69 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTagHelperCompletionService.cs b/src/Microsoft.VisualStudio.Editor.Razor/DefaultTagHelperCompletionService.cs index 7b927f48ad..dc8d55cb03 100644 --- a/src/Microsoft.VisualStudio.Editor.Razor/DefaultTagHelperCompletionService.cs +++ b/src/Microsoft.VisualStudio.Editor.Razor/DefaultTagHelperCompletionService.cs @@ -174,6 +174,11 @@ namespace Microsoft.VisualStudio.Editor.Razor foreach (var rule in possibleDescriptor.TagMatchingRules) { + if (!TagHelperMatchingConventions.SatisfiesParentTag(completionContext.ContainingTagName, rule)) + { + continue; + } + if (rule.TagName == TagHelperMatchingConventions.ElementCatchAllName) { catchAllDescriptors.Add(possibleDescriptor); @@ -210,7 +215,7 @@ namespace Microsoft.VisualStudio.Editor.Razor { foreach (var completionTagName in elementCompletions.Keys) { - if (elementCompletions[completionTagName].Count > 0 || + if (elementCompletions[completionTagName].Count > 0 || !string.IsNullOrEmpty(prefix) && completionTagName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { // The current completion either has other TagHelper's associated with it or is prefixed with a non-empty diff --git a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTagHelperCompletionServiceTest.cs b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTagHelperCompletionServiceTest.cs index aca20bcb3d..47fd565bb4 100644 --- a/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTagHelperCompletionServiceTest.cs +++ b/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultTagHelperCompletionServiceTest.cs @@ -838,6 +838,75 @@ namespace Microsoft.VisualStudio.Editor.Razor AssertCompletionsAreEquivalent(expectedCompletions, completions); } + [Fact] + public void GetElementCompletions_NoContainingParentTag_DoesNotGetCompletionForRuleWithParentTag() + { + // Arrange + var documentDescriptors = new[] + { + TagHelperDescriptorBuilder.Create("Tag1", "TestAssembly") + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("outer-child-tag")) + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("child-tag").RequireParentTag("parent-tag")) + .Build(), + TagHelperDescriptorBuilder.Create("Tag2", "TestAssembly") + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("parent-tag")) + .AllowChildTag("child-tag") + .Build(), + }; + var expectedCompletions = ElementCompletionResult.Create(new Dictionary>() + { + ["outer-child-tag"] = new HashSet { documentDescriptors[0] }, + ["parent-tag"] = new HashSet { documentDescriptors[1] }, + }); + + var completionContext = BuildElementCompletionContext( + documentDescriptors, + existingCompletions: Enumerable.Empty(), + containingTagName: null, + containingParentTagName: null); + var service = CreateTagHelperCompletionFactsService(); + + // Act + var completions = service.GetElementCompletions(completionContext); + + // Assert + AssertCompletionsAreEquivalent(expectedCompletions, completions); + } + + [Fact] + public void GetElementCompletions_WithContainingParentTag_GetsCompletionForRuleWithParentTag() + { + // Arrange + var documentDescriptors = new[] + { + TagHelperDescriptorBuilder.Create("Tag1", "TestAssembly") + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("outer-child-tag")) + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("child-tag").RequireParentTag("parent-tag")) + .Build(), + TagHelperDescriptorBuilder.Create("Tag2", "TestAssembly") + .TagMatchingRuleDescriptor(rule => rule.RequireTagName("parent-tag")) + .AllowChildTag("child-tag") + .Build(), + }; + var expectedCompletions = ElementCompletionResult.Create(new Dictionary>() + { + ["child-tag"] = new HashSet { documentDescriptors[0] }, + }); + + var completionContext = BuildElementCompletionContext( + documentDescriptors, + existingCompletions: Enumerable.Empty(), + containingTagName: "parent-tag", + containingParentTagName: null); + var service = CreateTagHelperCompletionFactsService(); + + // Act + var completions = service.GetElementCompletions(completionContext); + + // Assert + AssertCompletionsAreEquivalent(expectedCompletions, completions); + } + [Fact] public void GetElementCompletions_AllowedChildrenAreIgnoredWhenAtRoot() {