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); }
protected CompletionHelper(CompletionService completionService) { CompletionService = completionService; _language = CompletionService.Language; _rules = CompletionService.GetRules(); }
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; }
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() }); }