internal XSharpFormattingCommandHandler(IVsTextView textViewAdapter, ITextView textView,
                                                IBufferTagAggregatorFactoryService aggregator)
        {
            this._textView         = textView;
            this._textView.Closed += OnClosed;
            this._aggregator       = aggregator;
            //add this to the filter chain
            _linesToSync = new List <int>();
            //
            _buffer = _textView.TextBuffer;
            if (_buffer != null)
            {
                _buffer.ChangedLowPriority += Textbuffer_Changed;
                _buffer.Changing           += Textbuffer_Changing;
                _file = _buffer.GetFile();

                if (_buffer.CheckEditAccess())
                {
                    //formatCaseForWholeBuffer();
                }
            }
            if (_file != null)
            {
                _settings = EditorConfigReader.ReadSettings(_buffer, _file.FullPath);
            }

            textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
            registerClassifier();
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == typeof(VSConstants.VSStd97CmdID).GUID && _cmds.Contains(nCmdID))
            {
                ITextBuffer buffer = textView.TextBuffer;

                if (buffer.CheckEditAccess())
                {
                    RemoveTrailingWhitespace(buffer);
                }
            }
            return(NextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == new Guid("1496A755-94DE-11D0-8C3F-00C04FC2AAE2") && nCmdID == (uint)VSConstants.VSStd2KCmdID.DELETEWHITESPACE)
            {
                ITextBuffer buffer = textView.TextBuffer;

                if (buffer.CheckEditAccess())
                {
                    RemoveTrailingWhitespace(buffer);
                    return VSConstants.S_OK;
                }
            }
            return NextCommandTarget.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        }
Пример #4
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == new Guid("1496A755-94DE-11D0-8C3F-00C04FC2AAE2") && nCmdID == 64)
            {
                ITextBuffer buffer = _view.TextBuffer;

                if (buffer.CheckEditAccess())
                {
                    RemoveTrailingWhitespace(buffer);
                    return(VSConstants.S_OK);
                }
            }

            return(_nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            if (pguidCmdGroup == _cmdGgroup && _cmdId.Contains(nCmdID))
            {
                if (!IsEnabled())
                {
                    return(_nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                }

                ITextBuffer buffer = _view.TextBuffer;

                if (buffer != null && buffer.CheckEditAccess())
                {
                    RemoveTrailingWhitespace(buffer);
                }
            }

            return(_nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
        }
Пример #6
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);
        }
Пример #7
0
        private static bool ShouldWrapPrelim(
            bool optionsAutoWrapEnabled,
            int optionsAvoidWrappingBeforeLine,
            INormalizedTextChangeCollection changes,
            ITextSnapshot snapshot,
            ITextBuffer buffer,
            CaretPosition caretPosition,
            out SnapshotPoint caretPoint,
            out int firstLine)
        {
            caretPoint = default(SnapshotPoint);
            firstLine = -1;

            if (!optionsAutoWrapEnabled)
            {
                return false;
            }

            if (!buffer.CheckEditAccess())
            {
                return false;
            }

            // The auto-wrap should only apply during simple typing.  Region
            // edits (simultaneous multi-line typing) could lead to truly bizarre
            // wrapping behavior, so it really doesn't make sense.
            if (changes.Count > 1)
            {
                return false;
            }

            // Need a better (more testable!) way to get the editing state
            // (change, caret, etc.) out.  Perhaps we just take the hit and get
            // all of these up front instead of only calculating them as needed?
            var change = changes[0];
            caretPoint = caretPosition.Point.GetPoint(snapshot, caretPosition.Affinity).GetValueOrDefault();

            // If the caret isn't near the change, this was an undo, or other operation
            // we shouldn't wrap on!
            if ((caretPoint.Snapshot != snapshot) ||
                (caretPoint < change.NewPosition) ||
                (caretPoint > change.NewEnd))
            {
                return false;
            }

            firstLine = snapshot.GetLineNumberFromPosition(change.NewPosition);

            // If we're in the "don't auto-wrap" leading lines, bail.
            if (firstLine < optionsAvoidWrappingBeforeLine)
            {
                return false;
            }

            return true;
        }
Пример #8
0
#pragma warning restore 67

        /// <summary>
        /// Gets all the <see cref="ClassificationSpan"/> objects that intersect with the given range of text.
        /// </summary>
        /// <remarks>
        /// This method scans the given SnapshotSpan for potential matches for this classification.
        /// In this instance, it classifies everything and returns each span as a new ClassificationSpan.
        /// </remarks>
        /// <param name="span">The span currently being classified.</param>
        /// <returns>A list of ClassificationSpans that represent spans identified to be of this classification.</returns>
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            List <ClassificationSpan> spans = null;

            if (span.Snapshot.ContentType.DisplayName == "BuildOutput")
            {
                spans = new List <ClassificationSpan>();
                ITextBuffer textBuf       = span.Snapshot.TextBuffer;
                var         text          = span.GetText();
                int         indFNameBegin = text.IndexOf("__cp__.");
                if (indFNameBegin >= 0)
                {
                    if (text.IndexOf("__cp__.tracer.cpp") >= 0 || text.IndexOf("warning") >= 0)
                    {
                        if (textBuf.CheckEditAccess())
                        {
                            ITextEdit te = textBuf.CreateEdit();
                            te.Delete(span);
                            te.Apply();
                        }
                        //textBuf.Delete(span);
                    }
                    else if (text.IndexOf(" error ") >= 0)
                    {
                        int indFNameEnd = 0;
                        if ((indFNameEnd = text.IndexOf(' ', indFNameBegin)) < 0)
                        {
                            indFNameEnd = text.Length - 1;
                        }
                        string fName = text.Substring(indFNameBegin, indFNameEnd - indFNameBegin);
                        if (textBuf.CheckEditAccess())
                        {
                            ITextEdit te = textBuf.CreateEdit();
                            te.Replace(span, "[ERROR]: Failed to add chartpoints to " + fName + ". Please first check successful build in non [ChartPoints] configuration\n");
                            te.Apply();
                        }
                        //textBuf.Replace(span, "[ERROR]: Failed to add chartpoints to " + fName + ". Please first check successful build in non [ChartPoints] configuration\n");
                    }
                    else
                    {
                        text = text.Replace("__cp__.", "Instrumenting chartpoints for ");
                        if (textBuf.CheckEditAccess())
                        {
                            ITextEdit te = textBuf.CreateEdit();
                            te.Replace(span, text);
                            te.Apply();
                        }
                        //textBuf.Replace(span, text);
                    }
                }
            }
            else
            {
                spans = new List <ClassificationSpan>()
                {
                    new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, span.Length)), this.classificationType)
                };
            }

            return(spans);
        }
        private void ApplyPendingChanges()
        {
            if (_settings == null || _settings.KeywordCase == KeywordCase.None)
            {
                return;
            }
            // do not update buffer from background thread
            if (!_buffer.CheckEditAccess())
            {
                return;
            }

            if (_linesToSync.Count > 0)
            {
                int[] lines;
                lock (_linesToSync)
                {
                    lines = _linesToSync.ToArray();
                    _linesToSync.Clear();
                    _linesToSync.Add(this.getCurrentLine());
                    Array.Sort(lines);
                }

                // wait until we can work
                while (_buffer.EditInProgress)
                {
                    System.Threading.Thread.Sleep(100);
                }

                ThreadHelper.JoinableTaskFactory.Run(async delegate
                {
                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                    var editSession = _buffer.CreateEdit();
                    var snapshot    = editSession.Snapshot;
                    try
                    {
                        var end     = DateTime.Now + new TimeSpan(0, 0, 2);
                        int counter = 0;
                        foreach (int nLine in lines)
                        {
                            if (nLine < snapshot.LineCount && nLine >= 0)
                            {
                                ITextSnapshotLine line = snapshot.GetLineFromLineNumber(nLine);
                                FormatLineCase(editSession, line);
                            }
                            // when it takes longer than 2 seconds, then abort
                            if (++counter > 100 && DateTime.Now > end)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        ;
                    }
                    finally
                    {
                        if (editSession.HasEffectiveChanges)
                        {
                            editSession.Apply();
                        }
                        else
                        {
                            editSession.Cancel();
                        }
                    }
                });
            }
        }