Ejemplo n.º 1
0
            public void PreBackspace(out bool handledCommand)
            {
                handledCommand = false;

                var caretPos = this.GetCaretPosition();
                var snapshot = SubjectBuffer.CurrentSnapshot;

                if (caretPos.HasValue && caretPos.Value.Position > 0 && (caretPos.Value.Position - 1) == OpeningPoint.GetPoint(snapshot).Position &&
                    !HasForwardTyping)
                {
                    using var undo = CreateUndoTransaction();
                    using var edit = SubjectBuffer.CreateEdit();

                    var span = new SnapshotSpan(OpeningPoint.GetPoint(snapshot), ClosingPoint.GetPoint(snapshot));

                    edit.Delete(span);

                    if (edit.HasFailedChanges)
                    {
                        edit.Cancel();
                        undo.Cancel();
                        Debug.Fail("Unable to clear braces");
                    }
                    else
                    {
                        // handle the command so the backspace does
                        // not go through since we've already cleared the braces
                        handledCommand = true;
                        edit.ApplyAndLogExceptions();
                        undo.Complete();
                        EndSession();
                    }
                }
            }
            public void PostReturn()
            {
                _threadingContext.ThrowIfNotOnUIThread();
                if (this.GetCaretPosition().HasValue)
                {
                    var closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);

                    if (closingSnapshotPoint.Position > 0 && HasNoForwardTyping(this.GetCaretPosition().Value, closingSnapshotPoint.Subtract(1)))
                    {
                        var context = GetBraceCompletionContext();
                        if (context == null)
                        {
                            return;
                        }

                        var indentationOptions = context.Value.Document.GetIndentationOptionsAsync(_globalOptions, CancellationToken.None).WaitAndGetResult(CancellationToken.None);
                        var changesAfterReturn = _service.GetTextChangeAfterReturnAsync(context.Value, indentationOptions, CancellationToken.None).WaitAndGetResult(CancellationToken.None);
                        if (changesAfterReturn != null)
                        {
                            using var caretPreservingTransaction = new CaretPreservingEditTransaction(EditorFeaturesResources.Brace_Completion, _undoHistory, _editorOperations);
                            ApplyBraceCompletionResult(changesAfterReturn.Value);
                            caretPreservingTransaction.Complete();
                        }
                    }
                }
            }
            private void ApplyBraceCompletionResult(BraceCompletionResult result)
            {
                _threadingContext.ThrowIfNotOnUIThread();
                using var edit = SubjectBuffer.CreateEdit();
                foreach (var change in result.TextChanges)
                {
                    edit.Replace(change.Span.ToSpan(), change.NewText);
                }

                edit.ApplyAndLogExceptions();

                try
                {
                    Contract.ThrowIfFalse(SubjectBuffer.CurrentSnapshot[OpeningPoint.GetPosition(SubjectBuffer.CurrentSnapshot)] == OpeningBrace,
                                          "The opening point does not match the opening brace character");
                    Contract.ThrowIfFalse(SubjectBuffer.CurrentSnapshot[ClosingPoint.GetPosition(SubjectBuffer.CurrentSnapshot) - 1] == ClosingBrace,
                                          "The closing point does not match the closing brace character");
                }
                catch (Exception e) when(FatalError.ReportAndCatch(e))
                {
                    return;
                }

                var caretLine = SubjectBuffer.CurrentSnapshot.GetLineFromLineNumber(result.CaretLocation.Line);

                TextView.TryMoveCaretToAndEnsureVisible(new VirtualSnapshotPoint(caretLine, result.CaretLocation.Character));
            }
            private bool TryStart(CancellationToken cancellationToken)
            {
                this.AssertIsForeground();
                var closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);

                if (closingSnapshotPoint.Position < 1)
                {
                    Debug.Fail("The closing point was not found at the expected position.");
                    return(false);
                }

                var openingSnapshotPoint = closingSnapshotPoint.Subtract(1);

                if (openingSnapshotPoint.GetChar() != OpeningBrace)
                {
                    // there is a bug in editor brace completion engine on projection buffer that already fixed in vs_pro. until that is FIed to use
                    // I will make this not to assert
                    // Debug.Fail("The opening brace was not found at the expected position.");
                    return(false);
                }

                OpeningPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(openingSnapshotPoint, PointTrackingMode.Positive);

                var context = GetBraceCompletionContext();

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

                var braceResult = _service.GetBraceCompletionAsync(context.Value, cancellationToken).WaitAndGetResult(cancellationToken);

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

                using var caretPreservingTransaction = new CaretPreservingEditTransaction(EditorFeaturesResources.Brace_Completion, _undoHistory, _editorOperations);

                // Apply the change to complete the brace.
                ApplyBraceCompletionResult(braceResult.Value);

                // switch the closing point from positive to negative tracking so that the closing point stays against the closing brace
                ClosingPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot), PointTrackingMode.Negative);

                var contextAfterStart = GetBraceCompletionContext();

                if (contextAfterStart != null)
                {
                    var options           = IndentationOptions.FromDocumentAsync(contextAfterStart.Value.Document, cancellationToken).WaitAndGetResult(cancellationToken);
                    var changesAfterStart = _service.GetTextChangesAfterCompletionAsync(contextAfterStart.Value, options, cancellationToken).WaitAndGetResult(cancellationToken);
                    if (changesAfterStart != null)
                    {
                        ApplyBraceCompletionResult(changesAfterStart.Value);
                    }
                }

                caretPreservingTransaction.Complete();
                return(true);
            }
Ejemplo n.º 5
0
            public void PreOverType(out bool handledCommand)
            {
                handledCommand = false;
                if (ClosingPoint == null)
                {
                    return;
                }

                // Brace completion is not cancellable.
                var cancellationToken = CancellationToken.None;
                var snapshot          = this.SubjectBuffer.CurrentSnapshot;
                var document          = snapshot.GetOpenDocumentInCurrentContextWithChanges();

                SnapshotPoint closingSnapshotPoint = ClosingPoint.GetPoint(snapshot);

                if (!HasForwardTyping && _session.AllowOverType(this, cancellationToken))
                {
                    SnapshotPoint?caretPos = this.GetCaretPosition();

                    Debug.Assert(caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position);

                    // ensure that we are within the session before clearing
                    if (caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position && closingSnapshotPoint.Position > 0)
                    {
                        using (ITextUndoTransaction undo = CreateUndoTransaction())
                        {
                            _editorOperations.AddBeforeTextBufferChangePrimitive();

                            SnapshotSpan span = new SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1));

                            using (ITextEdit edit = SubjectBuffer.CreateEdit())
                            {
                                edit.Delete(span);

                                if (edit.HasFailedChanges)
                                {
                                    Debug.Fail("Unable to clear closing brace");
                                    edit.Cancel();
                                    undo.Cancel();
                                }
                                else
                                {
                                    handledCommand = true;

                                    edit.Apply();

                                    MoveCaretToClosingPoint();

                                    _editorOperations.AddAfterTextBufferChangePrimitive();

                                    undo.Complete();
                                }
                            }
                        }
                    }
                }
            }
Ejemplo n.º 6
0
            public void PostReturn()
            {
                if (this.GetCaretPosition().HasValue)
                {
                    SnapshotPoint closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);

                    if (closingSnapshotPoint.Position > 0 && HasNoForwardTyping(this.GetCaretPosition().Value, closingSnapshotPoint.Subtract(1)))
                    {
                        _session.AfterReturn(this, CancellationToken.None);
                    }
                }
            }
            private BraceCompletionContext GetBraceCompletionContext(ParsedDocument document)
            {
                _threadingContext.ThrowIfNotOnUIThread();
                var snapshot = SubjectBuffer.CurrentSnapshot;

                var closingSnapshotPoint = ClosingPoint.GetPosition(snapshot);
                var openingSnapshotPoint = OpeningPoint.GetPosition(snapshot);
                // The user is actively typing so the caret position should not be null.
                var caretPosition = this.GetCaretPosition().Value.Position;

                return(new BraceCompletionContext(document, openingSnapshotPoint, closingSnapshotPoint, caretPosition));
            }
Ejemplo n.º 8
0
            private void MoveCaretToClosingPoint()
            {
                SnapshotPoint closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);

                // find the position just after the closing brace in the view's text buffer
                SnapshotPoint?afterBrace = TextView.BufferGraph.MapUpToBuffer(closingSnapshotPoint,
                                                                              PointTrackingMode.Negative, PositionAffinity.Predecessor, TextView.TextBuffer);

                Debug.Assert(afterBrace.HasValue, "Unable to move caret to closing point");

                if (afterBrace.HasValue)
                {
                    TextView.Caret.MoveTo(afterBrace.Value);
                }
            }
            private BraceCompletionContext?GetBraceCompletionContext()
            {
                this.AssertIsForeground();
                var snapshot = SubjectBuffer.CurrentSnapshot;

                var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

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

                var closingSnapshotPoint = ClosingPoint.GetPosition(snapshot);
                var openingSnapshotPoint = OpeningPoint.GetPosition(snapshot);
                // The user is actively typing so the caret position should not be null.
                var caretPosition = this.GetCaretPosition().Value.Position;

                return(new BraceCompletionContext(document, openingSnapshotPoint, closingSnapshotPoint, caretPosition));
            }
Ejemplo n.º 10
0
            private void Start(CancellationToken cancellationToken)
            {
                // this is where the caret should go after the change
                SnapshotPoint  pos = TextView.Caret.Position.BufferPosition;
                ITrackingPoint beforeTrackingPoint = pos.Snapshot.CreateTrackingPoint(pos.Position, PointTrackingMode.Negative);

                ITextSnapshot snapshot             = SubjectBuffer.CurrentSnapshot;
                SnapshotPoint closingSnapshotPoint = ClosingPoint.GetPoint(snapshot);

                if (closingSnapshotPoint.Position < 1)
                {
                    Debug.Fail("The closing point was not found at the expected position.");
                    EndSession();
                    return;
                }

                SnapshotPoint openingSnapshotPoint = closingSnapshotPoint.Subtract(1);

                if (openingSnapshotPoint.GetChar() != OpeningBrace)
                {
                    // there is a bug in editor brace completion engine on projection buffer that already fixed in vs_pro. until that is FIed to use
                    // I will make this not to assert
                    // Debug.Fail("The opening brace was not found at the expected position.");
                    EndSession();
                    return;
                }

                OpeningPoint = snapshot.CreateTrackingPoint(openingSnapshotPoint, PointTrackingMode.Positive);
                var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

                if (!_session.CheckOpeningPoint(this, cancellationToken))
                {
                    EndSession();
                    return;
                }

                using (ITextUndoTransaction undo = CreateUndoTransaction())
                {
                    // insert the closing brace
                    using (ITextEdit edit = SubjectBuffer.CreateEdit())
                    {
                        edit.Insert(closingSnapshotPoint, ClosingBrace.ToString());

                        if (edit.HasFailedChanges)
                        {
                            Debug.Fail("Unable to insert closing brace");

                            // exit without setting the closing point which will take us off the stack
                            edit.Cancel();
                            undo.Cancel();
                            return;
                        }
                        else
                        {
                            snapshot = edit.Apply();
                        }
                    }

                    SnapshotPoint beforePoint = beforeTrackingPoint.GetPoint(TextView.TextSnapshot);

                    // switch from positive to negative tracking so it stays against the closing brace
                    ClosingPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(ClosingPoint.GetPoint(snapshot), PointTrackingMode.Negative);

                    Debug.Assert(ClosingPoint.GetPoint(snapshot).Position > 0 && (new SnapshotSpan(ClosingPoint.GetPoint(snapshot).Subtract(1), 1))
                                 .GetText().Equals(ClosingBrace.ToString()), "The closing point does not match the closing brace character");

                    // move the caret back between the braces
                    TextView.Caret.MoveTo(beforePoint);

                    _session.AfterStart(this, cancellationToken);

                    undo.Complete();
                }
            }
            public void PreOverType(out bool handledCommand)
            {
                _threadingContext.ThrowIfNotOnUIThread();
                handledCommand = false;
                if (ClosingPoint == null)
                {
                    return;
                }

                // Brace completion is not cancellable.
                var cancellationToken = CancellationToken.None;
                var snapshot          = this.SubjectBuffer.CurrentSnapshot;

                var closingSnapshotPoint = ClosingPoint.GetPoint(snapshot);

                if (!HasForwardTyping && AllowOverType())
                {
                    var caretPos = this.GetCaretPosition();

                    Debug.Assert(caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position);

                    // ensure that we are within the session before clearing
                    if (caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position && closingSnapshotPoint.Position > 0)
                    {
                        using var undo = CreateUndoTransaction();

                        _editorOperations.AddBeforeTextBufferChangePrimitive();

                        var span = new SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1));

                        using var edit = SubjectBuffer.CreateEdit();

                        edit.Delete(span);

                        if (edit.HasFailedChanges)
                        {
                            Debug.Fail("Unable to clear closing brace");
                            edit.Cancel();
                            undo.Cancel();
                        }
                        else
                        {
                            handledCommand = true;

                            edit.ApplyAndLogExceptions();

                            MoveCaretToClosingPoint();

                            _editorOperations.AddAfterTextBufferChangePrimitive();

                            undo.Complete();
                        }
                    }
                }

                return;

                bool AllowOverType()
                {
                    var context = GetBraceCompletionContext();

                    return(context != null && _service.AllowOverTypeAsync(context.Value, cancellationToken).WaitAndGetResult(cancellationToken));
                }
            }
            private bool TryStart(CancellationToken cancellationToken)
            {
                _threadingContext.ThrowIfNotOnUIThread();
                var closingSnapshotPoint = ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot);

                if (closingSnapshotPoint.Position < 1)
                {
                    Debug.Fail("The closing point was not found at the expected position.");
                    return(false);
                }

                var openingSnapshotPoint = closingSnapshotPoint.Subtract(1);

                if (openingSnapshotPoint.GetChar() != OpeningBrace)
                {
                    // there is a bug in editor brace completion engine on projection buffer that already fixed in vs_pro. until that is FIed to use
                    // I will make this not to assert
                    // Debug.Fail("The opening brace was not found at the expected position.");
                    return(false);
                }

                OpeningPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(openingSnapshotPoint, PointTrackingMode.Positive);

                var document = SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();

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

                var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
                var context        = GetBraceCompletionContext(parsedDocument);

                // Note: completes synchronously unless Semantic Model is needed to determine the result:
                if (!_service.HasBraceCompletionAsync(context, document, cancellationToken).WaitAndGetResult(cancellationToken))
                {
                    return(false);
                }

                var braceResult = _service.GetBraceCompletion(context);

                using var caretPreservingTransaction = new CaretPreservingEditTransaction(EditorFeaturesResources.Brace_Completion, _undoHistory, _editorOperations);

                // Apply the change to complete the brace.
                ApplyBraceCompletionResult(braceResult);

                // switch the closing point from positive to negative tracking so that the closing point stays against the closing brace
                ClosingPoint = SubjectBuffer.CurrentSnapshot.CreateTrackingPoint(ClosingPoint.GetPoint(SubjectBuffer.CurrentSnapshot), PointTrackingMode.Negative);

                if (TryGetBraceCompletionContext(out var contextAfterStart, cancellationToken))
                {
                    var indentationOptions = SubjectBuffer.GetIndentationOptions(_editorOptionsService, contextAfterStart.Document.LanguageServices, explicitFormat: false);
                    var changesAfterStart  = _service.GetTextChangesAfterCompletion(contextAfterStart, indentationOptions, cancellationToken);
                    if (changesAfterStart != null)
                    {
                        ApplyBraceCompletionResult(changesAfterStart.Value);
                    }
                }

                caretPreservingTransaction.Complete();
                return(true);
            }