Esempio n. 1
0
        private AsyncCompletionData.CommitBehavior Commit(
            Document document,
            CompletionService completionService,
            ITextView view,
            ITextBuffer subjectBuffer,
            RoslynCompletionItem roslynItem,
            TextSpan completionListSpan,
            char?commitCharacter,
            ITextSnapshot triggerSnapshot,
            CompletionRules rules,
            string filterText,
            CancellationToken cancellationToken)
        {
            AssertIsForeground();

            bool includesCommitCharacter;

            if (!subjectBuffer.CheckEditAccess())
            {
                // We are on the wrong thread.
                FatalError.ReportWithoutCrash(new InvalidOperationException("Subject buffer did not provide Edit Access"));
                return(AsyncCompletionData.CommitBehavior.None);
            }

            if (subjectBuffer.EditInProgress)
            {
                FatalError.ReportWithoutCrash(new InvalidOperationException("Subject buffer is editing by someone else."));
                return(AsyncCompletionData.CommitBehavior.None);
            }

            var change              = completionService.GetChangeAsync(document, roslynItem, completionListSpan, commitCharacter, cancellationToken).WaitAndGetResult(cancellationToken);
            var textChange          = change.TextChange;
            var triggerSnapshotSpan = new SnapshotSpan(triggerSnapshot, textChange.Span.ToSpan());
            var mappedSpan          = triggerSnapshotSpan.TranslateTo(subjectBuffer.CurrentSnapshot, SpanTrackingMode.EdgeInclusive);

            using (var edit = subjectBuffer.CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null))
            {
                edit.Replace(mappedSpan.Span, change.TextChange.NewText);

                // edit.Apply() may trigger changes made by extensions.
                // updatedCurrentSnapshot will contain changes made by Roslyn but not by other extensions.
                var updatedCurrentSnapshot = edit.Apply();

                if (change.NewPosition.HasValue)
                {
                    // Roslyn knows how to positionate the caret in the snapshot we just created.
                    // If there were more edits made by extensions, TryMoveCaretToAndEnsureVisible maps the snapshot point to the most recent one.
                    view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(updatedCurrentSnapshot, change.NewPosition.Value));
                }
                else
                {
                    // Or, If we're doing a minimal change, then the edit that we make to the
                    // buffer may not make the total text change that places the caret where we
                    // would expect it to go based on the requested change. In this case,
                    // determine where the item should go and set the care manually.

                    // Note: we only want to move the caret if the caret would have been moved
                    // by the edit.  i.e. if the caret was actually in the mapped span that
                    // we're replacing.
                    var caretPositionInBuffer = view.GetCaretPoint(subjectBuffer);
                    if (caretPositionInBuffer.HasValue && mappedSpan.IntersectsWith(caretPositionInBuffer.Value))
                    {
                        view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(subjectBuffer.CurrentSnapshot, mappedSpan.Start.Position + textChange.NewText.Length));
                    }
                    else
                    {
                        view.Caret.EnsureVisible();
                    }
                }

                includesCommitCharacter = change.IncludesCommitCharacter;

                if (roslynItem.Rules.FormatOnCommit)
                {
                    // The edit updates the snapshot however other extensions may make changes there.
                    // Therefore, it is required to use subjectBuffer.CurrentSnapshot for further calculations rather than the updated current snapsot defined above.
                    document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
                    var spanToFormat      = triggerSnapshotSpan.TranslateTo(subjectBuffer.CurrentSnapshot, SpanTrackingMode.EdgeInclusive);
                    var formattingService = document?.GetLanguageService <IEditorFormattingService>();

                    if (formattingService != null)
                    {
                        var changes = formattingService.GetFormattingChangesAsync(
                            document, spanToFormat.Span.ToTextSpan(), CancellationToken.None).WaitAndGetResult(CancellationToken.None);
                        document.Project.Solution.Workspace.ApplyTextChanges(document.Id, changes, CancellationToken.None);
                    }
                }
            }

            if (includesCommitCharacter)
            {
                return(AsyncCompletionData.CommitBehavior.SuppressFurtherTypeCharCommandHandlers);
            }

            if (commitCharacter == '\n' && SendEnterThroughToEditor(rules, roslynItem, filterText))
            {
                return(AsyncCompletionData.CommitBehavior.RaiseFurtherReturnKeyAndTabKeyCommandHandlers);
            }

            return(AsyncCompletionData.CommitBehavior.None);
        }
Esempio n. 2
0
 protected CompletionHelper(CompletionService completionService)
 {
     CompletionService = completionService;
     _language         = CompletionService.Language;
     _rules            = CompletionService.GetRules();
 }
Esempio n. 3
0
            public Session(Controller controller, ModelComputation <Model> computation, CompletionRules completionRules, ICompletionPresenterSession presenterSession)
                : base(controller, computation, presenterSession)
            {
                _completionRules = completionRules;

                this.PresenterSession.ItemCommitted += OnPresenterSessionItemCommitted;
                this.PresenterSession.ItemSelected  += OnPresenterSessionItemSelected;
            }
Esempio n. 4
0
        private static CompletionItem ConvertCompletionItem(LogicalDocument document, CompletionRules completionRules, CodeAnalysis.Completion.CompletionItem item)
        {
            var documentation = CommonCompletionItem.HasDescription(item)
                ? CommonCompletionItem.GetDescription(item).Text
                : string.Empty;

            return(new CompletionItem
            {
                Label = item.DisplayText,
                SortText = item.SortText,
                FilterText = item.FilterText,
                Kind = GetKind(item.Glyph),
                TextEdit = new TextEdit
                {
                    NewText = item.DisplayText,
                    Range = Helpers.ToRange(document, item.Span)
                },
                Documentation = documentation,
                CommitCharacters = completionRules.DefaultCommitCharacters.Select(x => x.ToString()).ToArray()
            });
        }