public void GetCompletionAt_AtAttributeEdge_BoolAttribute_ReturnsCompletionsWithout() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<test2 />", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(36 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Collection( completions, completion => { Assert.Equal("bool-val", completion.InsertText); Assert.Equal(TagHelperCompletionProvider.MinimizedAttributeCommitCharacters, completion.CommitCharacters); Assert.Equal(CompletionSortTextHelper.HighSortPriority, completion.SortText); }, completion => { Assert.Equal("int-val", completion.InsertText); Assert.Equal(TagHelperCompletionProvider.AttributeCommitCharacters, completion.CommitCharacters); Assert.Equal(CompletionSortTextHelper.HighSortPriority, completion.SortText); }); }
private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider) { var sourceDocument = RazorSourceDocument.Create(documentContent, RazorSourceDocumentProperties.Default); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument); var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, DefaultTagHelpers); var completionQueryLocation = new SourceSpan(queryIndex, length: 0); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); var razorCompletionItems = componentCompletionProvider.GetCompletionItems(context, completionQueryLocation); var completionList = RazorCompletionEndpoint.CreateLSPCompletionList( razorCompletionItems, new CompletionListCache(), new[] { ExtendedCompletionItemKinds.TagHelper }, new PlatformAgnosticCompletionCapability() { VSCompletionList = new VSCompletionListCapability() { CommitCharacters = true, Data = true, } }); return(completionList); }
private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider) { var sourceDocument = RazorSourceDocument.Create(documentContent, RazorSourceDocumentProperties.Default); var syntaxTree = RazorSyntaxTree.Parse(sourceDocument); var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: string.Empty, DefaultTagHelpers); var completionQueryLocation = new SourceSpan(queryIndex, length: 0); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); var razorCompletionItems = componentCompletionProvider.GetCompletionItems(context, completionQueryLocation); var completionList = RazorCompletionEndpoint.CreateLSPCompletionList( razorCompletionItems, new CompletionListCache(), new VSInternalClientCapabilities() { TextDocument = new TextDocumentClientCapabilities() { Completion = new VSInternalCompletionSetting() { CompletionItemKind = new CompletionItemKindSetting() { ValueSet = new[] { CompletionItemKind.TagHelper } }, CompletionList = new VSInternalCompletionListSetting() { CommitCharacters = true, Data = true, } } } }); return(completionList); }
public void GetCompletionAt_InBody_ParentRequiring_ReturnsCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<test1><</test1>", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(37 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Collection( completions, completion => { Assert.Equal("test1", completion.InsertText); }, completion => { Assert.Equal("SomeChild", completion.InsertText); }, completion => { Assert.Equal("test2", completion.InsertText); }); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorCompletionContext context, SourceSpan location) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (context.TagHelperDocumentContext is null) { throw new ArgumentNullException(nameof(context.TagHelperDocumentContext)); } if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind)) { // Directive attributes are only supported in components return(s_noDirectiveAttributeCompletionItems); } var change = new SourceChange(location, string.Empty); var owner = context.SyntaxTree.Root.LocateOwner(change); if (owner == null) { return(s_noDirectiveAttributeCompletionItems); } if (!TryGetAttributeInfo(owner, out _, out var attributeName, out var attributeNameLocation, out _, out _)) { // Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions. return(s_noDirectiveAttributeCompletionItems); } if (!attributeNameLocation.IntersectsWith(location.AbsoluteIndex)) { // We're trying to retrieve completions on a portion of the name that is not supported (such as a parameter). return(s_noDirectiveAttributeCompletionItems); } if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes)) { // This should never be the case, it means that we're operating on an attribute that doesn't have a tag. return(s_noDirectiveAttributeCompletionItems); } // At this point we've determined that completions have been requested for the name portion of the selected attribute. var completionItems = GetAttributeCompletions(attributeName, containingTagName, attributes, context.TagHelperDocumentContext); // We don't provide Directive Attribute completions when we're in the middle of // another unrelated (doesn't start with @) partially completed attribute. // <svg xml:| ></svg> (attributeName = "xml:") should not get any directive attribute completions. if (string.IsNullOrWhiteSpace(attributeName) || attributeName.StartsWith("@", StringComparison.Ordinal)) { return(completionItems); } return(s_noDirectiveAttributeCompletionItems); }
public async Task <CompletionContext> GetCompletionContextAsync( IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CancellationToken token) { try { var codeDocument = await Parser.GetLatestCodeDocumentAsync(triggerLocation.Snapshot, token); if (codeDocument is null) { return(CompletionContext.Empty); } var location = new SourceSpan(triggerLocation.Position, 0); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var razorCompletionContext = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); var razorCompletionItems = _completionFactsService.GetCompletionItems(razorCompletionContext, location); var completionItems = new List <CompletionItem>(); foreach (var razorCompletionItem in razorCompletionItems) { if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive) { // Don't support any other types of completion kinds other than directives. continue; } var completionItem = new CompletionItem( displayText: razorCompletionItem.DisplayText, filterText: razorCompletionItem.DisplayText, insertText: razorCompletionItem.InsertText, source: this, icon: DirectiveImageGlyph, filters: DirectiveCompletionFilters, suffix: string.Empty, sortText: razorCompletionItem.DisplayText, attributeIcons: ImmutableArray <ImageElement> .Empty); var completionDescription = razorCompletionItem.GetDirectiveCompletionDescription(); completionItem.Properties.AddProperty(DescriptionKey, completionDescription); completionItems.Add(completionItem); } var context = new CompletionContext(completionItems.ToImmutableArray()); return(context); } catch (OperationCanceledException) { return(CompletionContext.Empty); } }
public void GetCompletionItems_AttributeAreaInNonComponentFile_ReturnsEmptyList() { // Arrange var syntaxTree = GetSyntaxTree("<input />", FileKinds.Legacy); var location = new SourceSpan(7, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert Assert.Empty(result); }
public void GetCompletionItems_OutsideOfFile_ReturnsEmptyList() { // Arrange var syntaxTree = GetSyntaxTree("<input />"); var location = new SourceSpan(50, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert Assert.Empty(result); }
public void GetCompletionItems_ExistingAttribute_TrailingEdge_ReturnsEmptyList() { // Arrange var syntaxTree = GetSyntaxTree("<input src=\"xyz\" />"); var location = new SourceSpan(16, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert Assert.Empty(result); }
public void GetCompletionItems_ExistingAttribute_Partial_ReturnsEmptyList() { // Arrange var syntaxTree = GetSyntaxTree("<svg xml: ></svg>"); var location = new SourceSpan(9, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert Assert.Empty(result); }
public void GetCompletionAt_AtHtmlElementNameEdge_ReturnsNoCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<br />", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(32 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Empty(completions); }
public void GetCompletionAt_HtmlAttributeValue_DoesNotReturnCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<test2 class='' />", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(43 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Empty(completions); }
public void GetCompletionAt_InTagHelperAttribute_ReturnsCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<test2 int-val='123' />", DefaultTagHelpers); var sourceSpan = new SourceSpan(38 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Empty(completions); }
public void GetCompletionItems_InbetweenSelfClosingEnd_ReturnsEmptyList() { // Arrange var syntaxTree = GetSyntaxTree("<input /" + Environment.NewLine); var location = new SourceSpan(8, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert Assert.Empty(result); }
public void GetCompletionsAt_MalformedAttributeNamePrefix_ReturnsCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<test2 int->", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(36 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert AssertBoolIntCompletions(completions); }
public void GetCompletionItems_ExistingAttribute_Partial_ReturnsEmptyCollection() { // Arrange var codeDocument = GetCodeDocument("<svg xml: ></svg>"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(9, 0); var razorCompletionContext = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(razorCompletionContext, span); // Assert Assert.Empty(completions); }
public void GetCompletionItems_ExistingAttribute_TrailingEdge_ReturnsEmptyCollection() { // Arrange var codeDocument = GetCodeDocument("<input src=\"xyz\" />"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(16, 0); var razorCompletionContext = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(razorCompletionContext, span); // Assert Assert.Empty(completions); }
public void GetCompletionItems_AttributeAreaEndOfOpeningTag_ReturnsEmptyCollection() { // Arrange var codeDocument = GetCodeDocument("<input @bind:fo ></input>"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(16, 0); var razorCompletionContext = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(razorCompletionContext, span); // Assert Assert.Empty(completions); }
public void GetCompletionItems_OnDirectiveAttributeName_attributes_ReturnsCompletions() { // Arrange var codeDocument = GetCodeDocument("<input @ />"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(8, 0); var razorCompletionContext = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(razorCompletionContext, span); // Assert AssertContains(completions, "attributes", "@attributes", new[] { "=" }); }
public void GetCompletionItems_LocationHasNoOwner_ReturnsEmptyCollection() { // Arrange var codeDocument = GetCodeDocument("<input @ />"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(30, 0); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(context, span); // Assert Assert.Empty(completions); }
public void GetCompletionItems_AttributeAreaInIncompleteComponent_ReturnsTransitionCompletionItem() { // Arrange var syntaxTree = GetSyntaxTree("<svg xml:base=\"d\"></svg>"); var location = new SourceSpan(5, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert var item = Assert.Single(result); Assert.Same(item, TransitionCompletionItem); }
public void GetCompletionItems_AttributeAreaEndOfOpeningTag_ReturnsTransitionCompletionItem() { // Arrange var syntaxTree = GetSyntaxTree("<input ></input>"); var location = new SourceSpan(7, 0); var context = new RazorCompletionContext(syntaxTree, TagHelperDocumentContext); // Act var result = Provider.GetCompletionItems(context, location); // Assert var item = Assert.Single(result); Assert.Same(item, TransitionCompletionItem); }
public void GetCompletionItems_OnDirectiveAttributeName_ReturnsEmptyCollection() { // Arrange var codeDocument = GetCodeDocument("<input @bind:fo />"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(8, 0); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(context, span); // Assert Assert.Empty(completions); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorCompletionContext context, SourceSpan location) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (context.TagHelperDocumentContext is null) { throw new ArgumentNullException(nameof(context.TagHelperDocumentContext)); } if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind)) { // Directive attribute parameters are only supported in components return(Array.Empty <RazorCompletionItem>()); } var change = new SourceChange(location, string.Empty); var owner = context.SyntaxTree.Root.LocateOwner(change); if (owner == null) { return(Array.Empty <RazorCompletionItem>()); } if (!TryGetAttributeInfo(owner, out _, out var attributeName, out _, out var parameterName, out var parameterNameLocation)) { // Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions. return(Array.Empty <RazorCompletionItem>()); } if (!parameterNameLocation.IntersectsWith(location.AbsoluteIndex)) { // We're trying to retrieve completions on a portion of the name that is not supported (such as the name, i.e., |@bind|:format). return(Array.Empty <RazorCompletionItem>()); } if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes)) { // This should never be the case, it means that we're operating on an attribute that doesn't have a tag. return(Array.Empty <RazorCompletionItem>()); } var completions = GetAttributeParameterCompletions(attributeName, parameterName, containingTagName, attributes, context.TagHelperDocumentContext); return(completions); }
public void GetCompletionAt_AtEmptyTagName_ReturnsCompletions() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<", DefaultTagHelpers); var sourceSpan = new SourceSpan(30 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Collection( completions, completion => Assert.Equal("test1", completion.InsertText), completion => Assert.Equal("test2", completion.InsertText)); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorCompletionContext context, SourceSpan location) { if (context is null) { throw new ArgumentNullException(nameof(context)); } var completions = new List <RazorCompletionItem>(); if (ShouldProvideCompletions(context, location)) { var directiveCompletions = GetDirectiveCompletionItems(context.SyntaxTree); completions.AddRange(directiveCompletions); } return(completions); }
public void GetDirectiveCompletionItems_AllProvidersCompletionItems() { // Arrange var syntaxTree = RazorSyntaxTree.Parse(TestRazorSourceDocument.Create()); var tagHelperDocumentContext = TagHelperDocumentContext.Create(prefix: null, Enumerable.Empty <TagHelperDescriptor>()); var completionItem1 = new RazorCompletionItem("displayText1", "insertText1", RazorCompletionItemKind.Directive); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); var provider1 = Mock.Of <RazorCompletionItemProvider>(p => p.GetCompletionItems(context, default) == new[] { completionItem1 }, MockBehavior.Strict); var completionItem2 = new RazorCompletionItem("displayText2", "insertText2", RazorCompletionItemKind.Directive); var provider2 = Mock.Of <RazorCompletionItemProvider>(p => p.GetCompletionItems(context, default) == new[] { completionItem2 }, MockBehavior.Strict); var completionFactsService = new DefaultRazorCompletionFactsService(new[] { provider1, provider2 }); // Act var completionItems = completionFactsService.GetCompletionItems(context, default); // Assert Assert.Equal(new[] { completionItem1, completionItem2 }, completionItems); }
public void GetCompletionItems_OnDirectiveAttributeParameter_ReturnsCompletions() { // Arrange var codeDocument = GetCodeDocument("<input @bind:fo />"); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var span = new SourceSpan(14, 0); var context = new RazorCompletionContext(syntaxTree, tagHelperDocumentContext); // Act var completions = Provider.GetCompletionItems(context, span); // Assert Assert.Equal(3, completions.Count); AssertContains(completions, "culture"); AssertContains(completions, "event"); AssertContains(completions, "format"); }
public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorCompletionContext context, SourceSpan location) { if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind)) { // Directive attributes are only supported in components return(Array.Empty <RazorCompletionItem>()); } var change = new SourceChange(location, string.Empty); var owner = context.SyntaxTree.Root.LocateOwner(change); if (owner is null) { return(Array.Empty <RazorCompletionItem>()); } var attribute = owner.Parent; if (attribute is MarkupMiscAttributeContentSyntax && attribute.ContainsOnlyWhitespace()) { // This represents a tag when there's no attribute content <InputText | />. return(s_completions); } if (!TryGetAttributeInfo(owner, out var prefixLocation, out var attributeName, out var attributeNameLocation, out _, out _)) { return(Array.Empty <RazorCompletionItem>()); } if (attributeNameLocation.IntersectsWith(location.AbsoluteIndex) && attributeName.StartsWith("@", StringComparison.Ordinal)) { // The transition is already provided for the attribute name return(Array.Empty <RazorCompletionItem>()); } if (!IsValidCompletionPoint(location, prefixLocation, attributeNameLocation)) { // Not operating in the attribute name area return(Array.Empty <RazorCompletionItem>()); } // This represents a tag when there's no attribute content <InputText | />. return(s_completions); }
public void GetCompletionAt_KnownHtmlElement_ReturnsCompletions_DefaultPriority() { // Arrange var service = new TagHelperCompletionProvider(RazorTagHelperCompletionService, HtmlFactsService, TagHelperFactsService); var codeDocument = CreateCodeDocument($"@addTagHelper *, TestAssembly{Environment.NewLine}<title mutator />", isRazorFile: false, DefaultTagHelpers); var sourceSpan = new SourceSpan(36 + Environment.NewLine.Length, 0); var context = new RazorCompletionContext(codeDocument.GetSyntaxTree(), codeDocument.GetTagHelperContext()); // Act var completions = service.GetCompletionItems(context, sourceSpan); // Assert Assert.Collection( completions, completion => { Assert.Equal("Extra", completion.InsertText); Assert.Equal(TagHelperCompletionProvider.MinimizedAttributeCommitCharacters, completion.CommitCharacters); Assert.Equal("Extra", completion.SortText); }); }