Ensure output hint descriptors don't schema check.

- Prior to this if you had a `TagHelper` whos output hint was not in the final form of the completions we'd fall through into a schema check which resulted in a completion being added when it shouldn't. Example: `TagHelper` for `my-tr` that has an output hint of `tr` would end up getting added to the completion list under `body` because `my-tr` was not in the schema and would then be treated like the `environment` `TagHelper` (a new element).
- Added a test to validate that `TagHelper`s with output hints are cross referenced vs. existing completions and do not fall through to a schema check.

#1225
This commit is contained in:
N. Taylor Mullen 2017-04-14 11:38:59 -07:00
parent 0b17f14d68
commit d273c6cd4c
2 changed files with 42 additions and 4 deletions

View File

@ -62,11 +62,13 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
{ {
addRuleCompletions = true; addRuleCompletions = true;
} }
else if (outputHint != null && elementCompletions.ContainsKey(outputHint)) else if (outputHint != null)
{ {
// If the possible descriptors final output tag already exists in our list of completions, we should add every representation // If the current descriptor has an output hint we need to make sure it shows up only when its output hint would normally show up.
// of that descriptor to the possible element completions. // Example: We have a MyTableTagHelper that has an output hint of "table" and a MyTrTagHelper that has an output hint of "tr".
addRuleCompletions = true; // If we try typing in a situation like this: <body > | </body>
// We'd expect to only get "my-table" as a completion because the "body" tag doesn't allow "tr" tags.
addRuleCompletions = elementCompletions.ContainsKey(outputHint);
} }
else if (!completionContext.InHTMLSchema(rule.TagName)) else if (!completionContext.InHTMLSchema(rule.TagName))
{ {

View File

@ -10,6 +10,42 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor
{ {
public class DefaultTagHelperCompletionServiceTest public class DefaultTagHelperCompletionServiceTest
{ {
[Fact]
public void GetElementCompletions_TagOutputHintDoesNotFallThroughToSchemaCheck()
{
// Arrange
var documentDescriptors = new[]
{
TagHelperDescriptorBuilder.Create("MyTableTagHelper", "TestAssembly")
.TagMatchingRule(rule => rule.RequireTagName("my-table"))
.TagOutputHint("table")
.Build(),
TagHelperDescriptorBuilder.Create("MyTrTagHelper", "TestAssembly")
.TagMatchingRule(rule => rule.RequireTagName("my-tr"))
.TagOutputHint("tr")
.Build(),
};
var expectedCompletions = ElementCompletionResult.Create(new Dictionary<string, HashSet<TagHelperDescriptor>>()
{
["my-table"] = new HashSet<TagHelperDescriptor> { documentDescriptors[0] },
["table"] = new HashSet<TagHelperDescriptor>(),
});
var existingCompletions = new[] { "table" };
var completionContext = BuildCompletionContext(
documentDescriptors,
existingCompletions,
containingTagName: "body",
containingParentTagName: null);
var service = CreateTagHelperCompletionFactsService();
// Act
var completions = service.GetElementCompletions(completionContext);
// Assert
AssertCompletionsAreEquivalent(expectedCompletions, completions);
}
[Fact] [Fact]
public void GetElementCompletions_CatchAllsOnlyApplyToCompletionsStartingWithPrefix() public void GetElementCompletions_CatchAllsOnlyApplyToCompletionsStartingWithPrefix()
{ {