Exemplo n.º 1
0
        /// <summary>
        /// Attempts to convert VS Completion trigger into Roslyn completion trigger
        /// </summary>
        /// <param name="trigger">VS completion trigger</param>
        /// <param name="triggerLocation">Character.
        /// VS provides Backspace and Delete characters inside the trigger while Roslyn needs the char deleted by the trigger.
        /// Therefore, we provide this character separately and use it for Delete and Backspace cases only.
        /// We retrieve this character from triggerLocation.
        /// </param>
        /// <returns>Roslyn completion trigger</returns>
        internal static RoslynTrigger GetRoslynTrigger(AsyncCompletionData.CompletionTrigger trigger, SnapshotPoint triggerLocation)
        {
            switch (trigger.Reason)
            {
            case AsyncCompletionData.CompletionTriggerReason.InvokeAndCommitIfUnique:
                return(new RoslynTrigger(CompletionTriggerKind.InvokeAndCommitIfUnique));

            case AsyncCompletionData.CompletionTriggerReason.Insertion:
                return(RoslynTrigger.CreateInsertionTrigger(trigger.Character));

            case AsyncCompletionData.CompletionTriggerReason.Deletion:
            case AsyncCompletionData.CompletionTriggerReason.Backspace:
                var  snapshotBeforeEdit = trigger.ViewSnapshotBeforeTrigger;
                char characterRemoved;
                if (triggerLocation.Position >= 0 && triggerLocation.Position < snapshotBeforeEdit.Length)
                {
                    // If multiple characters were removed (selection), this finds the first character from the left.
                    characterRemoved = snapshotBeforeEdit[triggerLocation.Position];
                }
                else
                {
                    characterRemoved = (char)0;
                }

                return(RoslynTrigger.CreateDeletionTrigger(characterRemoved));

            case AsyncCompletionData.CompletionTriggerReason.SnippetsMode:
                return(new RoslynTrigger(CompletionTriggerKind.Snippets));

            default:
                return(RoslynTrigger.Invoke);
            }
        }
        protected async Task CheckResultsAsync(
            Document document, int position, string expectedItemOrNull,
            string expectedDescriptionOrNull, bool usePreviousCharAsTrigger,
            bool checkForAbsence, int?glyph, int?matchPriority,
            bool?hasSuggestionModeItem, string displayTextSuffix)
        {
            var code = (await document.GetTextAsync()).ToString();

            var trigger = CompletionTrigger.Invoke;

            if (usePreviousCharAsTrigger)
            {
                trigger = CompletionTrigger.CreateInsertionTrigger(insertedCharacter: code.ElementAt(position - 1));
            }

            var completionService = GetCompletionService(document.Project.Solution.Workspace);
            var completionList    = await GetCompletionListAsync(completionService, document, position, trigger);

            var items = completionList == null ? ImmutableArray <CompletionItem> .Empty : completionList.Items;

            if (hasSuggestionModeItem != null)
            {
                Assert.Equal(hasSuggestionModeItem.Value, completionList.SuggestionModeItem != null);
            }

            if (checkForAbsence)
            {
                if (items == null)
                {
                    return;
                }

                if (expectedItemOrNull == null)
                {
                    Assert.Empty(items);
                }
                else
                {
                    AssertEx.None(
                        items,
                        c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                        (expectedDescriptionOrNull != null ? completionService.GetDescriptionAsync(document, c).Result.Text == expectedDescriptionOrNull : true));
                }
            }
            else
            {
                if (expectedItemOrNull == null)
                {
                    Assert.NotEmpty(items);
                }
                else
                {
                    AssertEx.Any(items, c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                                 CompareItems(c.DisplayTextSuffix, displayTextSuffix ?? "") &&
                                 (expectedDescriptionOrNull != null ? completionService.GetDescriptionAsync(document, c).Result.Text == expectedDescriptionOrNull : true) &&
                                 (glyph.HasValue ? c.Tags.SequenceEqual(GlyphTags.GetTags((Glyph)glyph.Value)) : true) &&
                                 (matchPriority.HasValue ? (int)c.Rules.MatchPriority == matchPriority.Value : true));
                }
            }
        }
        private void VerifyTextualTriggerCharacterWorker(
            string markup, bool expectedTriggerCharacter, bool triggerOnLetter)
        {
            using (var workspace = CreateWorkspace(markup))
            {
                var document = workspace.Documents.Single();
                var position = document.CursorPosition.Value;
                var text     = document.TextBuffer.CurrentSnapshot.AsText();
                var options  = workspace.Options.WithChangedOption(
                    CompletionOptions.TriggerOnTypingLetters, document.Project.Language, triggerOnLetter);
                var trigger = CompletionTrigger.CreateInsertionTrigger(text[position]);

                var service = GetCompletionService(workspace);
                var isTextualTriggerCharacterResult = service.ShouldTriggerCompletion(text, position + 1, trigger, options: options);

                if (expectedTriggerCharacter)
                {
                    var assertText = "'" + text.ToString(new TextSpan(position, 1)) + "' expected to be textual trigger character";
                    Assert.True(isTextualTriggerCharacterResult, assertText);
                }
                else
                {
                    var assertText = "'" + text.ToString(new TextSpan(position, 1)) + "' expected to NOT be textual trigger character";
                    Assert.False(isTextualTriggerCharacterResult, assertText);
                }
            }
        }
        protected async Task <ImmutableArray <CompletionItem> > GetCompletionItemsAsync(
            string markup, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger = false)
        {
            MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), out var code, out int position);
            var document = WorkspaceFixture.UpdateDocument(code, sourceCodeKind);

            var trigger = usePreviousCharAsTrigger
                ? CompletionTrigger.CreateInsertionTrigger(insertedCharacter: code.ElementAt(position - 1))
                : CompletionTrigger.Invoke;

            var completionService = GetCompletionService(document.Project.Solution.Workspace);
            var completionList    = await GetCompletionListAsync(completionService, document, position, trigger);

            return(completionList == null ? ImmutableArray <CompletionItem> .Empty : completionList.Items);
        }