Exemple #1
0
        public void TryConvert_DirectiveAttribute_Snippet_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("@testDisplay...", "testInsert", RazorCompletionItemKind.DirectiveAttribute);

            completionItem.SetAttributeCompletionDescription(new AttributeCompletionDescription(new CodeAnalysis.Razor.Completion.AttributeDescriptionInfo[] {
                new CodeAnalysis.Razor.Completion.AttributeDescriptionInfo("System.String", "System.String", "@testDisplay", "This is docs")
            }));
            var descriptionFactory = new Mock <TagHelperDescriptionFactory>();
            var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory);
            var capability         = new CompletionCapability {
                CompletionItem = new CompletionItemCapability {
                    SnippetSupport = true
                }
            };

            completionEndpoint.SetCapability(capability);
            var expectedInsert = "testInsert$1=\"$2\"$0";

            // Act
            var result = completionEndpoint.TryConvert(completionItem, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(expectedInsert, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
            Assert.True(converted.TryGetRazorCompletionKind(out var convertedKind));
            Assert.Equal(RazorCompletionItemKind.DirectiveAttribute, convertedKind);
        }
Exemple #2
0
        public void TryConvert_Directive_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("testDisplay", "testInsert", RazorCompletionItemKind.Directive);
            var description    = "Something";

            completionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription(description));
            var descriptionFactory = new Mock <TagHelperDescriptionFactory>();
            var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory);

            completionEndpoint.SetCapability(DefaultCapability);

            // Act
            var result = completionEndpoint.TryConvert(completionItem, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.DisplayText, converted.FilterText);
            Assert.Equal(completionItem.DisplayText, converted.SortText);
            Assert.Equal(description, converted.Detail);
            Assert.NotNull(converted.Documentation);
            Assert.True(converted.TryGetRazorCompletionKind(out var convertedKind));
            Assert.Equal(RazorCompletionItemKind.Directive, convertedKind);
        }
        public async Task Handle_Resolve_TagHelperAttribute_ReturnsCompletionItemWithDocumentation()
        {
            // Arrange
            var descriptionFactory = new Mock <TagHelperTooltipFactory>(MockBehavior.Strict);
            var markdown           = new MarkupContent
            {
                Kind  = MarkupKind.Markdown,
                Value = "Some Markdown"
            };

            descriptionFactory.Setup(factory => factory.TryCreateTooltip(It.IsAny <AggregateBoundAttributeDescription>(), out markdown))
            .Returns(true);
            var completionEndpoint  = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, descriptionFactory.Object, LoggerFactory);
            var razorCompletionItem = new RazorCompletionItem("TestItem", "TestItem", RazorCompletionItemKind.TagHelperAttribute);

            razorCompletionItem.SetAttributeCompletionDescription(new AggregateBoundAttributeDescription(Array.Empty <BoundAttributeDescriptionInfo>()));
            var completionList = completionEndpoint.CreateLSPCompletionList(new[] { razorCompletionItem });
            var completionItem = completionList.Items.Single();

            // Act
            var newCompletionItem = await completionEndpoint.Handle(completionItem, default);

            // Assert
            Assert.NotNull(newCompletionItem.Documentation);
        }
        public static void SetTagHelperAttributeDescriptionInfo(this RazorCompletionItem completionItem, AttributeDescriptionInfo attributeDescriptionInfo)
        {
            if (completionItem is null)
            {
                throw new ArgumentNullException(nameof(completionItem));
            }

            completionItem.Items[TagHelperAttributeCompletionDescriptionKey] = attributeDescriptionInfo;
        }
        public static AttributeDescriptionInfo?GetTagHelperAttributeDescriptionInfo(this RazorCompletionItem completionItem)
        {
            if (completionItem is null)
            {
                throw new ArgumentNullException(nameof(completionItem));
            }

            var description = completionItem.Items[TagHelperAttributeCompletionDescriptionKey] as AttributeDescriptionInfo;

            return(description);
        }
Exemple #6
0
        public void TryConvert_Directive_SerializationDoesNotThrow()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("testDisplay", "testInsert", RazorCompletionItemKind.Directive);
            var description    = "Something";

            completionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription(description));
            RazorCompletionEndpoint.TryConvert(completionItem, SupportedCompletionItemKinds, out var converted);

            // Act & Assert
            JsonConvert.SerializeObject(converted);
        }
        public void TryGet_SetCompletionList_ReturnsTrue()
        {
            // Arrange
            var completionList = new RazorCompletionItem[1];
            var resultId       = CompletionListCache.Set(completionList);

            // Act
            var result = CompletionListCache.TryGet(resultId, out var retrievedCompletionList);

            // Assert
            Assert.True(result);
            Assert.Same(completionList, retrievedCompletionList);
        }
Exemple #8
0
        public void TryConvert_Directive_SerializationDoesNotThrow()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("testDisplay", "testInsert", RazorCompletionItemKind.Directive);
            var description    = "Something";

            completionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription(description));
            var descriptionFactory = new Mock <TagHelperDescriptionFactory>();
            var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory);

            completionEndpoint.SetCapability(DefaultCapability);
            completionEndpoint.TryConvert(completionItem, out var converted);

            // Act & Assert
            JsonConvert.SerializeObject(converted);
        }
        public async Task Handle_Resolve_MarkupTransitionCompletion_ReturnsCompletionItemWithDocumentation()
        {
            // Arrange
            var descriptionFactory  = Mock.Of <TagHelperTooltipFactory>(MockBehavior.Strict);
            var completionEndpoint  = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, descriptionFactory, LoggerFactory);
            var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);

            razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
            var completionList = completionEndpoint.CreateLSPCompletionList(new[] { razorCompletionItem });
            var completionItem = completionList.Items.Single();

            // Act
            var newCompletionItem = await completionEndpoint.Handle(completionItem, default);

            // Assert
            Assert.NotNull(newCompletionItem.Documentation);
        }
Exemple #10
0
        public void TryConvert_TagHelperAttribute_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.TagHelperAttribute);

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, SupportedCompletionItemKinds, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
        }
Exemple #11
0
        public void TryConvert_DirectiveAttributeParameter_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.DirectiveAttributeParameter);

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, ClientCapabilities, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
        }
Exemple #12
0
        public void TryConvert_TagHelperAttribute_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format=\"$0\"", RazorCompletionItemKind.TagHelperAttribute, isSnippet: true);

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, ClientCapabilities, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal("format=\"$0\"", converted.InsertText);
            Assert.Equal(InsertTextFormat.Snippet, converted.InsertTextFormat);
            Assert.Equal(completionItem.DisplayText, converted.FilterText);
            Assert.Equal(completionItem.DisplayText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
        }
        public async Task Handle_Resolve_MarkupTransitionCompletion_ReturnsCompletionItemWithDocumentation()
        {
            // Arrange
            var endpoint = new RazorCompletionResolveEndpoint(LSPTagHelperTooltipFactory, VSLSPTagHelperTooltipFactory, CompletionListCache, LoggerFactory);

            endpoint.GetRegistration(DefaultClientCapability);
            var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);

            razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
            var completionList = CreateLSPCompletionList(new[] { razorCompletionItem });
            var completionItem = completionList.Items.Single();
            var parameters     = ConvertToBridgedItem(completionItem);

            // Act
            var newCompletionItem = await endpoint.Handle(parameters, default);

            // Assert
            Assert.NotNull(newCompletionItem.Documentation);
        }
        public void TryGet_EvictedCompletionList_ReturnsFalse()
        {
            // Arrange
            var initialCompletionList         = new RazorCompletionItem[1];
            var initialCompletionListResultId = CompletionListCache.Set(initialCompletionList);

            for (var i = 0; i < CompletionListCache.MaxCacheSize; i++)
            {
                // We now fill the completion list cache up until its cache max so that the initial completion list we set gets evicted.
                CompletionListCache.Set(new RazorCompletionItem[1]);
            }

            // Act
            var result = CompletionListCache.TryGet(initialCompletionListResultId, out var retrievedCompletionList);

            // Assert
            Assert.False(result);
            Assert.Null(retrievedCompletionList);
        }
Exemple #15
0
        public void TryConvert_DirectiveAttribute_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("@testDisplay", "testInsert", RazorCompletionItemKind.DirectiveAttribute, new[] { "=", ":" });

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, SupportedCompletionItemKinds, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Equal(completionItem.CommitCharacters, converted.CommitCharacters);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
        }
Exemple #16
0
        public void TryConvert_Directive_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("testDisplay", "testInsert", RazorCompletionItemKind.Directive);
            var description    = "Something";

            completionItem.SetDirectiveCompletionDescription(new DirectiveCompletionDescription(description));

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, SupportedCompletionItemKinds, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.DisplayText, converted.FilterText);
            Assert.Equal(completionItem.DisplayText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
        }
Exemple #17
0
        public async Task Handle_Resolve_MarkupTransitionCompletion_ReturnsCompletionItemWithDocumentation()
        {
            // Arrange
            var languageServer = new Mock <ClientNotifierServiceBase>(MockBehavior.Strict);

            languageServer.Setup(ls => ls.ClientSettings).Returns(new InitializeParams());
            var completionEndpoint = new RazorCompletionEndpoint(
                Dispatcher, EmptyDocumentResolver, CompletionFactsService, LSPTagHelperTooltipFactory, VSLSPTagHelperTooltipFactory, languageServer.Object, LoggerFactory);
            var razorCompletionItem = new RazorCompletionItem("@...", "@", RazorCompletionItemKind.MarkupTransition);

            razorCompletionItem.SetMarkupTransitionCompletionDescription(new MarkupTransitionCompletionDescription("Test description"));
            var completionList = completionEndpoint.CreateLSPCompletionList(new[] { razorCompletionItem });
            var completionItem = completionList.Items.Single();

            // Act
            var newCompletionItem = await completionEndpoint.Handle(completionItem, default);

            // Assert
            Assert.NotNull(newCompletionItem.Documentation);
        }
        public void TryConvert_DirectiveAttributeParameter_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.DirectiveAttributeParameter);

            completionItem.SetAttributeCompletionDescription(new AttributeCompletionDescription(Array.Empty <CodeAnalysis.Razor.Completion.AttributeDescriptionInfo>()));

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
            Assert.True(converted.TryGetRazorCompletionKind(out var convertedKind));
            Assert.Equal(RazorCompletionItemKind.DirectiveAttributeParameter, convertedKind);
        }
        private IReadOnlyList <RazorCompletionItem> GetElementCompletions(
            SyntaxNode containingTag,
            string containingTagName,
            IEnumerable <KeyValuePair <string, string> > attributes,
            TagHelperDocumentContext tagHelperDocumentContext)
        {
            var ancestors = containingTag.Ancestors();

            var(ancestorTagName, ancestorIsTagHelper) = _tagHelperFactsService.GetNearestAncestorTagInfo(ancestors);
            var elementCompletionContext = new ElementCompletionContext(
                tagHelperDocumentContext,
                existingCompletions: Enumerable.Empty <string>(),
                containingTagName,
                attributes,
                ancestorTagName,
                ancestorIsTagHelper,
                HtmlFactsService.IsHtmlTagName);

            var completionItems  = new List <RazorCompletionItem>();
            var completionResult = _tagHelperCompletionService.GetElementCompletions(elementCompletionContext);

            foreach (var completion in completionResult.Completions)
            {
                var razorCompletionItem = new RazorCompletionItem(
                    displayText: completion.Key,
                    insertText: completion.Key,
                    RazorCompletionItemKind.TagHelperElement,
                    ElementCommitCharacters);

                var tagHelperDescriptions = completion.Value.Select(tagHelper => new TagHelperDescriptionInfo(tagHelper.GetTypeName(), tagHelper.Documentation));
                var elementDescription    = new ElementDescriptionInfo(tagHelperDescriptions.ToList());
                razorCompletionItem.SetTagHelperElementDescriptionInfo(elementDescription);

                completionItems.Add(razorCompletionItem);
            }

            return(completionItems);
        }
        public void TryConvert_DirectiveAttributeParameter_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.DirectiveAttributeParameter);
            completionItem.SetAttributeCompletionDescription(new AttributeCompletionDescription(Array.Empty<CodeAnalysis.Razor.Completion.AttributeDescriptionInfo>()));
            var descriptionFactory = new Mock<TagHelperDescriptionFactory>();
            var completionEndpoint = new RazorCompletionEndpoint(Dispatcher, EmptyDocumentResolver, CompletionFactsService, TagHelperCompletionService, descriptionFactory.Object, LoggerFactory);

            // Act
            var result = completionEndpoint.TryConvert(completionItem, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
            Assert.True(converted.TryGetRazorCompletionKind(out var convertedKind));
            Assert.Equal(RazorCompletionItemKind.DirectiveAttributeParameter, convertedKind);
        }
        public void TryConvert_TagHelperAttribute_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.TagHelperAttribute);

            completionItem.SetTagHelperAttributeDescriptionInfo(new AttributeDescriptionInfo(Array.Empty <TagHelperAttributeDescriptionInfo>()));

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal(completionItem.InsertText, converted.InsertText);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
            var descriptionInfo = completionItem.GetTagHelperAttributeDescriptionInfo();

            Assert.NotNull(descriptionInfo);
        }
Exemple #22
0
        public void TryConvert_TagHelperAttribute_ForBool_ReturnsTrue()
        {
            // Arrange
            var completionItem = new RazorCompletionItem("format", "format", RazorCompletionItemKind.TagHelperAttribute);
            var attributeCompletionDescription = new AggregateBoundAttributeDescription(new[] {
                new BoundAttributeDescriptionInfo("System.Boolean", "Stuff", "format", "SomeDocs")
            });

            completionItem.SetAttributeCompletionDescription(attributeCompletionDescription);

            // Act
            var result = RazorCompletionEndpoint.TryConvert(completionItem, ClientCapabilities, out var converted);

            // Assert
            Assert.True(result);
            Assert.Equal(completionItem.DisplayText, converted.Label);
            Assert.Equal("format", converted.InsertText);
            Assert.Equal(InsertTextFormat.Plaintext, converted.InsertTextFormat);
            Assert.Equal(completionItem.InsertText, converted.FilterText);
            Assert.Equal(completionItem.InsertText, converted.SortText);
            Assert.Null(converted.Detail);
            Assert.Null(converted.Documentation);
            Assert.Null(converted.Command);
        }
        public static AggregateBoundElementDescription?GetTagHelperElementDescriptionInfo(this RazorCompletionItem completionItem)
        {
            if (completionItem is null)
            {
                throw new ArgumentNullException(nameof(completionItem));
            }

            var description = completionItem.Items[s_tagHelperElementCompletionDescriptionKey] as AggregateBoundElementDescription;

            return(description);
        }
Exemple #24
0
        // Internal for testing
        internal static bool TryConvert(RazorCompletionItem razorCompletionItem, out CompletionItem completionItem)
        {
            switch (razorCompletionItem.Kind)
            {
            case RazorCompletionItemKind.Directive:
            {
                // There's not a lot of calculation needed for Directives, go ahead and store the documentation/detail
                // on the completion item.
                var descriptionInfo         = razorCompletionItem.GetDirectiveCompletionDescription();
                var directiveCompletionItem = new CompletionItem()
                {
                    Label         = razorCompletionItem.DisplayText,
                    InsertText    = razorCompletionItem.InsertText,
                    FilterText    = razorCompletionItem.DisplayText,
                    SortText      = razorCompletionItem.DisplayText,
                    Detail        = descriptionInfo.Description,
                    Documentation = descriptionInfo.Description,
                    Kind          = CompletionItemKind.Struct,
                };

                if (razorCompletionItem == DirectiveAttributeTransitionCompletionItemProvider.TransitionCompletionItem)
                {
                    directiveCompletionItem.Command   = RetriggerCompletionCommand;
                    directiveCompletionItem.Kind      = CompletionItemKind.TypeParameter;
                    directiveCompletionItem.Preselect = true;
                }

                directiveCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = directiveCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttribute:
            {
                var descriptionInfo = razorCompletionItem.GetAttributeCompletionDescription();

                var directiveAttributeCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                };

                var indexerCompletion = razorCompletionItem.DisplayText.EndsWith("...");
                if (TryResolveDirectiveAttributeInsertionSnippet(razorCompletionItem.InsertText, indexerCompletion, descriptionInfo, out var snippetText))
                {
                    directiveAttributeCompletionItem.InsertText       = snippetText;
                    directiveAttributeCompletionItem.InsertTextFormat = InsertTextFormat.Snippet;
                }

                directiveAttributeCompletionItem.SetDescriptionInfo(descriptionInfo);
                directiveAttributeCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = directiveAttributeCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttributeParameter:
            {
                var descriptionInfo         = razorCompletionItem.GetAttributeCompletionDescription();
                var parameterCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                };

                parameterCompletionItem.SetDescriptionInfo(descriptionInfo);
                parameterCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = parameterCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.MarkupTransition:
            {
                var descriptionInfo = razorCompletionItem.GetMarkupTransitionCompletionDescription();
                var markupTransitionCompletionItem = new CompletionItem()
                {
                    Label            = razorCompletionItem.DisplayText,
                    InsertText       = razorCompletionItem.InsertText,
                    FilterText       = razorCompletionItem.DisplayText,
                    SortText         = razorCompletionItem.DisplayText,
                    Detail           = descriptionInfo.Description,
                    Documentation    = descriptionInfo.Description,
                    Kind             = CompletionItemKind.TypeParameter,
                    CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters)
                };

                completionItem = markupTransitionCompletionItem;
                return(true);
            }
            }

            completionItem = null;
            return(false);
        }
        private IReadOnlyList <RazorCompletionItem> GetAttributeCompletions(
            SyntaxNode containingAttribute,
            string containingTagName,
            string?selectedAttributeName,
            IEnumerable <KeyValuePair <string, string> > attributes,
            TagHelperDocumentContext tagHelperDocumentContext)
        {
            var ancestors = containingAttribute.Parent.Ancestors();
            var nonDirectiveAttributeTagHelpers = tagHelperDocumentContext.TagHelpers.Where(tagHelper => !tagHelper.BoundAttributes.Any(attribute => attribute.IsDirectiveAttribute()));
            var filteredContext = TagHelperDocumentContext.Create(tagHelperDocumentContext.Prefix, nonDirectiveAttributeTagHelpers);

            var(ancestorTagName, ancestorIsTagHelper) = _tagHelperFactsService.GetNearestAncestorTagInfo(ancestors);
            var attributeCompletionContext = new AttributeCompletionContext(
                filteredContext,
                existingCompletions: Enumerable.Empty <string>(),
                containingTagName,
                selectedAttributeName,
                attributes,
                ancestorTagName,
                ancestorIsTagHelper,
                HtmlFactsService.IsHtmlTagName);

            var completionItems  = new List <RazorCompletionItem>();
            var completionResult = _tagHelperCompletionService.GetAttributeCompletions(attributeCompletionContext);

            foreach (var completion in completionResult.Completions)
            {
                var filterText = completion.Key;

                // This is a little bit of a hack because the information returned by _razorTagHelperCompletionService.GetAttributeCompletions
                // does not have enough information for us to determine if a completion is an indexer completion or not. Therefore we have to
                // jump through a few hoops below to:
                //   1. Determine if this specific completion is an indexer based completion
                //   2. Resolve an appropriate snippet if it is. This is more troublesome because we need to remove the ... suffix to accurately
                //      build a snippet that makes sense for the user to type.
                var indexerCompletion = filterText.EndsWith("...", StringComparison.Ordinal);
                if (indexerCompletion)
                {
                    filterText = filterText.Substring(0, filterText.Length - 3);
                }

                var attributeCommitCharacters = ResolveAttributeCommitCharacters(completion.Value, indexerCompletion);

                var razorCompletionItem = new RazorCompletionItem(
                    displayText: completion.Key,
                    insertText: filterText,
                    RazorCompletionItemKind.TagHelperAttribute,
                    attributeCommitCharacters);

                var attributeDescriptions = completion.Value.Select(boundAttribute => new TagHelperAttributeDescriptionInfo(
                                                                        boundAttribute.DisplayName,
                                                                        boundAttribute.GetPropertyName(),
                                                                        indexerCompletion ? boundAttribute.IndexerTypeName : boundAttribute.TypeName,
                                                                        boundAttribute.Documentation));
                var attributeDescriptionInfo = new AttributeDescriptionInfo(attributeDescriptions.ToList());
                razorCompletionItem.SetTagHelperAttributeDescriptionInfo(attributeDescriptionInfo);

                completionItems.Add(razorCompletionItem);
            }

            return(completionItems);
        }
Exemple #26
0
        private IReadOnlyList <RazorCompletionItem> GetAttributeCompletions(
            SyntaxNode containingAttribute,
            string containingTagName,
            string?selectedAttributeName,
            IEnumerable <KeyValuePair <string, string> > attributes,
            TagHelperDocumentContext tagHelperDocumentContext,
            RazorCompletionOptions options)
        {
            var ancestors = containingAttribute.Parent.Ancestors();
            var nonDirectiveAttributeTagHelpers = tagHelperDocumentContext.TagHelpers.Where(tagHelper => !tagHelper.BoundAttributes.Any(attribute => attribute.IsDirectiveAttribute()));
            var filteredContext = TagHelperDocumentContext.Create(tagHelperDocumentContext.Prefix, nonDirectiveAttributeTagHelpers);

            var(ancestorTagName, ancestorIsTagHelper) = _tagHelperFactsService.GetNearestAncestorTagInfo(ancestors);
            var attributeCompletionContext = new AttributeCompletionContext(
                filteredContext,
                existingCompletions: Enumerable.Empty <string>(),
                containingTagName,
                selectedAttributeName,
                attributes,
                ancestorTagName,
                ancestorIsTagHelper,
                HtmlFactsService.IsHtmlTagName);

            var completionItems  = new List <RazorCompletionItem>();
            var completionResult = _tagHelperCompletionService.GetAttributeCompletions(attributeCompletionContext);

            foreach (var completion in completionResult.Completions)
            {
                var filterText = completion.Key;

                // This is a little bit of a hack because the information returned by _razorTagHelperCompletionService.GetAttributeCompletions
                // does not have enough information for us to determine if a completion is an indexer completion or not. Therefore we have to
                // jump through a few hoops below to:
                //   1. Determine if this specific completion is an indexer based completion
                //   2. Resolve an appropriate snippet if it is. This is more troublesome because we need to remove the ... suffix to accurately
                //      build a snippet that makes sense for the user to type.
                var indexerCompletion = filterText.EndsWith("...", StringComparison.Ordinal);
                if (indexerCompletion)
                {
                    filterText = filterText.Substring(0, filterText.Length - 3);
                }

                var attributeContext          = ResolveAttributeContext(completion.Value, indexerCompletion, options.SnippetsSupported);
                var attributeCommitCharacters = ResolveAttributeCommitCharacters(attributeContext);
                var isSnippet  = false;
                var insertText = filterText;
                if (TryResolveInsertText(insertText, attributeContext, out var snippetText))
                {
                    isSnippet  = true;
                    insertText = snippetText;
                }

                // We change the sort text depending on the tag name due to TagHelper/non-TagHelper concerns. For instance lets say you have a TagHelper that binds to `input`.
                // Chances are you're expecting to get every other `input` completion item in addition to the TagHelper completion items and the sort order should be the default
                // because HTML completion items are 100% as applicable as other items.
                //
                // Next assume that we have a TagHelper that binds `custom` (or even `Custom`); this is a special scenario where the user has effectively created a new HTML tag
                // meaning they're probably expecting to provide all of the attributes necessary for that tag to operate. Meaning, HTML attribute completions are less important.
                // To make sure we prioritize our attribute completions above all other types of completions we set the priority to high so they're showed in the completion list
                // above all other completion items.
                var sortText            = HtmlFactsService.IsHtmlTagName(containingTagName) ? CompletionSortTextHelper.DefaultSortPriority : CompletionSortTextHelper.HighSortPriority;
                var razorCompletionItem = new RazorCompletionItem(
                    displayText: completion.Key,
                    insertText: insertText,
                    sortText: sortText,
                    kind: RazorCompletionItemKind.TagHelperAttribute,
                    commitCharacters: attributeCommitCharacters,
                    isSnippet: isSnippet);

                var attributeDescriptions = completion.Value.Select(boundAttribute =>
                {
                    var descriptionInfo = BoundAttributeDescriptionInfo.From(boundAttribute, indexerCompletion);

                    return(descriptionInfo);
                });
                var attributeDescriptionInfo = new AggregateBoundAttributeDescription(attributeDescriptions.ToList());
                razorCompletionItem.SetAttributeCompletionDescription(attributeDescriptionInfo);

                completionItems.Add(razorCompletionItem);
            }

            return(completionItems);
        }
        // Internal for testing
        internal static bool TryConvert(
            RazorCompletionItem razorCompletionItem,
            IReadOnlyList <ExtendedCompletionItemKinds> supportedItemKinds,
            out CompletionItem completionItem)
        {
            if (razorCompletionItem is null)
            {
                throw new ArgumentNullException(nameof(razorCompletionItem));
            }

            var tagHelperCompletionItemKind = CompletionItemKind.TypeParameter;

            if (supportedItemKinds?.Contains(ExtendedCompletionItemKinds.TagHelper) == true)
            {
                tagHelperCompletionItemKind = (CompletionItemKind)ExtendedCompletionItemKinds.TagHelper;
            }

            switch (razorCompletionItem.Kind)
            {
            case RazorCompletionItemKind.Directive:
            {
                var directiveCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.DisplayText,
                    SortText   = razorCompletionItem.DisplayText,
                    Kind       = CompletionItemKind.Struct,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    directiveCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                if (razorCompletionItem == DirectiveAttributeTransitionCompletionItemProvider.TransitionCompletionItem)
                {
                    directiveCompletionItem.Command = RetriggerCompletionCommand;
                    directiveCompletionItem.Kind    = tagHelperCompletionItemKind;
                }

                completionItem = directiveCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttribute:
            {
                var directiveAttributeCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = tagHelperCompletionItemKind,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    directiveAttributeCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                completionItem = directiveAttributeCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttributeParameter:
            {
                var parameterCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = tagHelperCompletionItemKind,
                };

                completionItem = parameterCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.MarkupTransition:
            {
                var markupTransitionCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.DisplayText,
                    SortText   = razorCompletionItem.DisplayText,
                    Kind       = tagHelperCompletionItemKind,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    markupTransitionCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                completionItem = markupTransitionCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.TagHelperElement:
            {
                var tagHelperElementCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = tagHelperCompletionItemKind,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    tagHelperElementCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                completionItem = tagHelperElementCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.TagHelperAttribute:
            {
                var tagHelperAttributeCompletionItem = new CompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = tagHelperCompletionItemKind,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    tagHelperAttributeCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                completionItem = tagHelperAttributeCompletionItem;
                return(true);
            }
            }

            completionItem = null;
            return(false);
        }
Exemple #28
0
        // Internal for testing
        internal static bool TryConvert(RazorCompletionItem razorCompletionItem, out CompletionItem completionItem)
        {
            if (razorCompletionItem is null)
            {
                throw new ArgumentNullException(nameof(razorCompletionItem));
            }

            switch (razorCompletionItem.Kind)
            {
            case RazorCompletionItemKind.Directive:
            {
                // There's not a lot of calculation needed for Directives, go ahead and store the documentation
                // on the completion item.
                var descriptionInfo         = razorCompletionItem.GetDirectiveCompletionDescription();
                var directiveCompletionItem = new VSLspCompletionItem()
                {
                    Label         = razorCompletionItem.DisplayText,
                    InsertText    = razorCompletionItem.InsertText,
                    FilterText    = razorCompletionItem.DisplayText,
                    SortText      = razorCompletionItem.DisplayText,
                    Documentation = descriptionInfo.Description,
                    Kind          = CompletionItemKind.Struct,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    directiveCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                if (razorCompletionItem == DirectiveAttributeTransitionCompletionItemProvider.TransitionCompletionItem)
                {
                    directiveCompletionItem.Command = RetriggerCompletionCommand;
                    directiveCompletionItem.Kind    = CompletionItemKind.TypeParameter;
                    directiveCompletionItem.Icon    = VSLspCompletionItemIcons.TagHelper;
                }

                directiveCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = directiveCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttribute:
            {
                var descriptionInfo = razorCompletionItem.GetAttributeCompletionDescription();

                var directiveAttributeCompletionItem = new VSLspCompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                    Icon       = VSLspCompletionItemIcons.TagHelper,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    directiveAttributeCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                directiveAttributeCompletionItem.SetDescriptionInfo(descriptionInfo);
                directiveAttributeCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = directiveAttributeCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.DirectiveAttributeParameter:
            {
                var descriptionInfo         = razorCompletionItem.GetAttributeCompletionDescription();
                var parameterCompletionItem = new VSLspCompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                    Icon       = VSLspCompletionItemIcons.TagHelper,
                };

                parameterCompletionItem.SetDescriptionInfo(descriptionInfo);
                parameterCompletionItem.SetRazorCompletionKind(razorCompletionItem.Kind);
                completionItem = parameterCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.MarkupTransition:
            {
                var descriptionInfo = razorCompletionItem.GetMarkupTransitionCompletionDescription();
                var markupTransitionCompletionItem = new VSLspCompletionItem()
                {
                    Label         = razorCompletionItem.DisplayText,
                    InsertText    = razorCompletionItem.InsertText,
                    FilterText    = razorCompletionItem.DisplayText,
                    SortText      = razorCompletionItem.DisplayText,
                    Documentation = descriptionInfo.Description,
                    Kind          = CompletionItemKind.TypeParameter,
                    Icon          = VSLspCompletionItemIcons.TagHelper,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    markupTransitionCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                completionItem = markupTransitionCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.TagHelperElement:
            {
                var tagHelperElementCompletionItem = new VSLspCompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                    Icon       = VSLspCompletionItemIcons.TagHelper,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    tagHelperElementCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                var descriptionInfo = razorCompletionItem.GetTagHelperElementDescriptionInfo();
                tagHelperElementCompletionItem.SetDescriptionInfo(descriptionInfo);

                completionItem = tagHelperElementCompletionItem;
                return(true);
            }

            case RazorCompletionItemKind.TagHelperAttribute:
            {
                var tagHelperAttributeCompletionItem = new VSLspCompletionItem()
                {
                    Label      = razorCompletionItem.DisplayText,
                    InsertText = razorCompletionItem.InsertText,
                    FilterText = razorCompletionItem.InsertText,
                    SortText   = razorCompletionItem.InsertText,
                    Kind       = CompletionItemKind.TypeParameter,
                    Icon       = VSLspCompletionItemIcons.TagHelper,
                };

                if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0)
                {
                    tagHelperAttributeCompletionItem.CommitCharacters = new Container <string>(razorCompletionItem.CommitCharacters);
                }

                var descriptionInfo = razorCompletionItem.GetTagHelperAttributeDescriptionInfo();
                tagHelperAttributeCompletionItem.SetDescriptionInfo(descriptionInfo);

                completionItem = tagHelperAttributeCompletionItem;
                return(true);
            }
            }

            completionItem = null;
            return(false);
        }
 public static void SetTagHelperElementDescriptionInfo(this RazorCompletionItem completionItem, ElementDescriptionInfo elementDescriptionInfo)
 {
     completionItem.Items[TagHelperElementCompletionDescriptionKey] = elementDescriptionInfo;
 }
 public static void SetTagHelperElementDescriptionInfo(this RazorCompletionItem completionItem, AggregateBoundElementDescription elementDescriptionInfo)
 {
     completionItem.Items[s_tagHelperElementCompletionDescriptionKey] = elementDescriptionInfo;
 }