Allow catch-all THDs to apply to all completions.
- Prior to this catch-alls were explicitly ignored not to populate the IntelliSense with an excess amount of `TagHelper`s. To maintain backwards compatible expectations this commit reverts that expectation. - Scoped an existing test to only test its primary scenario. - Added a new test to verify that catch-alls accurately apply to all completions (including dynamically added ones). #1219
This commit is contained in:
parent
cd486226d6
commit
46a5ca972f
|
|
@ -44,18 +44,20 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
_ => new HashSet<TagHelperDescriptor>(),
|
_ => new HashSet<TagHelperDescriptor>(),
|
||||||
StringComparer.OrdinalIgnoreCase);
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var catchAllDescriptors = new HashSet<TagHelperDescriptor>();
|
||||||
var possibleChildDescriptors = _tagHelperFactsService.GetTagHelpersGivenParent(completionContext.DocumentContext, completionContext.ContainingTagName);
|
var possibleChildDescriptors = _tagHelperFactsService.GetTagHelpersGivenParent(completionContext.DocumentContext, completionContext.ContainingTagName);
|
||||||
foreach (var possibleDescriptor in possibleChildDescriptors)
|
foreach (var possibleDescriptor in possibleChildDescriptors)
|
||||||
{
|
{
|
||||||
var addRuleCompletions = false;
|
var addRuleCompletions = false;
|
||||||
var outputHint = possibleDescriptor.TagOutputHint;
|
var outputHint = possibleDescriptor.TagOutputHint;
|
||||||
|
|
||||||
// Filter out catch-all rules because TagHelpers that target attributes only would light up every child tag otherwise. Force those TagHelpers
|
foreach (var rule in possibleDescriptor.TagMatchingRules)
|
||||||
// to have additional requirements before showing them in the element completion list.
|
|
||||||
var nonCatchAllRules = possibleDescriptor.TagMatchingRules.Where(rule => rule.TagName != TagHelperMatchingConventions.ElementCatchAllName);
|
|
||||||
foreach (var rule in nonCatchAllRules)
|
|
||||||
{
|
{
|
||||||
if (elementCompletions.ContainsKey(rule.TagName))
|
if (rule.TagName == TagHelperMatchingConventions.ElementCatchAllName)
|
||||||
|
{
|
||||||
|
catchAllDescriptors.Add(possibleDescriptor);
|
||||||
|
}
|
||||||
|
else if (elementCompletions.ContainsKey(rule.TagName))
|
||||||
{
|
{
|
||||||
addRuleCompletions = true;
|
addRuleCompletions = true;
|
||||||
}
|
}
|
||||||
|
|
@ -74,19 +76,35 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
|
|
||||||
if (addRuleCompletions)
|
if (addRuleCompletions)
|
||||||
{
|
{
|
||||||
if (!elementCompletions.TryGetValue(rule.TagName, out var existingRuleDescriptors))
|
UpdateCompletions(rule.TagName, possibleDescriptor);
|
||||||
{
|
|
||||||
existingRuleDescriptors = new HashSet<TagHelperDescriptor>();
|
|
||||||
elementCompletions[rule.TagName] = existingRuleDescriptors;
|
|
||||||
}
|
|
||||||
|
|
||||||
existingRuleDescriptors.Add(possibleDescriptor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We needed to track all catch-alls and update their completions after all other completions have been completed.
|
||||||
|
// This way, any TagHelper added completions will also have catch-alls listed under their entries.
|
||||||
|
foreach (var catchAllDescriptor in catchAllDescriptors)
|
||||||
|
{
|
||||||
|
foreach (var completionTagNames in elementCompletions.Keys)
|
||||||
|
{
|
||||||
|
UpdateCompletions(completionTagNames, catchAllDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var result = ElementCompletionResult.Create(elementCompletions);
|
var result = ElementCompletionResult.Create(elementCompletions);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
void UpdateCompletions(string tagName, TagHelperDescriptor possibleDescriptor)
|
||||||
|
{
|
||||||
|
if (!elementCompletions.TryGetValue(tagName, out var existingRuleDescriptors))
|
||||||
|
{
|
||||||
|
existingRuleDescriptors = new HashSet<TagHelperDescriptor>();
|
||||||
|
elementCompletions[tagName] = existingRuleDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
existingRuleDescriptors.Add(possibleDescriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAllowedChildrenCompletions(
|
private void AddAllowedChildrenCompletions(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,39 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
{
|
{
|
||||||
public class DefaultTagHelperCompletionServiceTest
|
public class DefaultTagHelperCompletionServiceTest
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetElementCompletions_CatchAllsApplyToAllCompletions()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var documentDescriptors = new[]
|
||||||
|
{
|
||||||
|
TagHelperDescriptorBuilder.Create("SuperLiTagHelper", "TestAssembly")
|
||||||
|
.TagMatchingRule(rule => rule.RequireTagName("superli"))
|
||||||
|
.Build(),
|
||||||
|
TagHelperDescriptorBuilder.Create("CatchAll", "TestAssembly")
|
||||||
|
.TagMatchingRule(rule => rule.RequireTagName("*"))
|
||||||
|
.Build(),
|
||||||
|
};
|
||||||
|
var expectedCompletions = ElementCompletionResult.Create(new Dictionary<string, HashSet<TagHelperDescriptor>>()
|
||||||
|
{
|
||||||
|
["superli"] = new HashSet<TagHelperDescriptor> { documentDescriptors[0], documentDescriptors[1] },
|
||||||
|
["li"] = new HashSet<TagHelperDescriptor> { documentDescriptors[1] },
|
||||||
|
});
|
||||||
|
|
||||||
|
var existingCompletions = new[] { "li" };
|
||||||
|
var completionContext = BuildCompletionContext(
|
||||||
|
documentDescriptors,
|
||||||
|
existingCompletions,
|
||||||
|
containingTagName: "ul");
|
||||||
|
var service = CreateTagHelperCompletionFactsService();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var completions = service.GetElementCompletions(completionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
AssertCompletionsAreEquivalent(expectedCompletions, completions);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetElementCompletions_AllowsMultiTargetingTagHelpers()
|
public void GetElementCompletions_AllowsMultiTargetingTagHelpers()
|
||||||
{
|
{
|
||||||
|
|
@ -183,13 +216,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
|
||||||
.AllowChildTag("div")
|
.AllowChildTag("div")
|
||||||
.Build(),
|
.Build(),
|
||||||
};
|
};
|
||||||
var expectedCompletions = ElementCompletionResult.Create(new Dictionary<string, HashSet<TagHelperDescriptor>>()
|
var expectedCompletions = ElementCompletionResult.Create(new Dictionary<string, HashSet<TagHelperDescriptor>>());
|
||||||
{
|
|
||||||
["p"] = new HashSet<TagHelperDescriptor>(),
|
|
||||||
["em"] = new HashSet<TagHelperDescriptor>(),
|
|
||||||
});
|
|
||||||
|
|
||||||
var existingCompletions = new[] { "p", "em" };
|
var existingCompletions = Enumerable.Empty<string>();
|
||||||
var completionContext = BuildCompletionContext(
|
var completionContext = BuildCompletionContext(
|
||||||
documentDescriptors,
|
documentDescriptors,
|
||||||
existingCompletions,
|
existingCompletions,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue