Ejemplo n.º 1
0
        private bool TryInvokeSnippetCompletion(TabKeyCommandArgs args)
        {
            var subjectBuffer = args.SubjectBuffer;
            var caretPoint    = args.TextView.GetCaretPoint(subjectBuffer).Value.Position;

            var text = subjectBuffer.AsTextContainer().CurrentText;

            // If the user types "<line start><spaces><question><tab>"
            // then the editor takes over and shows the normal *full* snippet picker UI.
            // i.e. the picker with all the folders and snippet organization.
            //
            // However, if the user instead has something like
            //
            //      "<line start><spaces><identifier><question><tab>"
            //
            // Then we take over and we show a completion list with all snippets in it
            // in a flat list.  This enables simple browsing and filtering of all items
            // based on what the user typed so far.
            //
            // If we detect this pattern, then we delete the previous character (the
            // question mark) and we don't send the tab through to the editor.  In
            // essence, the <quesiton><tab> acts as the trigger, and we act as if that
            // text never makes it into the buffer.

            if (!Workspace.TryGetWorkspace(subjectBuffer.AsTextContainer(), out var workspace))
            {
                return(false);
            }

            var documentId = workspace.GetDocumentIdInCurrentContext(subjectBuffer.AsTextContainer());

            if (documentId == null)
            {
                return(false);
            }

            var document = workspace.CurrentSolution.GetDocument(documentId);

            if (document == null)
            {
                return(false);
            }

            // There's was a buffer-Document mapping. We should be able
            // to get a CompletionService.
            var completionService = GetCompletionService();

            Contract.ThrowIfNull(completionService, nameof(completionService));

            var rules = completionService.GetRules();

            if (rules.SnippetsRule != SnippetsRule.IncludeAfterTypingIdentifierQuestionTab)
            {
                return(false);
            }

            var syntaxFactsOpt = document.GetLanguageService <ISyntaxFactsService>();

            if (syntaxFactsOpt == null ||
                caretPoint < 2 ||
                text[caretPoint - 1] != '?' ||
                !CompletionSource.QuestionMarkIsPrecededByIdentifierAndWhitespace(text, caretPoint - 1, syntaxFactsOpt))
            {
                return(false);
            }

            // Because <question><tab> is actually a command to bring up snippets,
            // we delete the last <question> that was typed.
            var textChange = new TextChange(TextSpan.FromBounds(caretPoint - 1, caretPoint), string.Empty);

            workspace.ApplyTextChanges(documentId, textChange, CancellationToken.None);
            this.StartNewModelComputation(
                completionService, new CompletionTrigger(CompletionTriggerKind.Snippets));
            return(true);
        }